2014-06-12 66 views
2

我有两个不同类型的签名功能:如何获得的功能特性

f :: Int -> [a] -> [a] 
g :: (Int, Int) -> [a] -> [a] 

第一个参数确定功能运行在列表的长度。例如,f可能在长度为p-1的列表上运行,并且g分别在第一自变量p(p,e)上的长度为p^(e-1)的列表上操作。

我使用fg作为需要知道此长度函数(h的第一个参数)的另一个函数h :: Int -> ([a] -> [a]) -> [a] -> [a]的参数。我觉得自己目前做的是:

\p -> h (p-1) (f p) 
\(p,e) -> h (p^(e-1)) (g (p,e)) 

我到处结合使用hfg。这种重复是容易出错和混乱的。

目标是找到一种避免将参数长度传递给h的方法。相反,h应该能够根据函数参数确定自己的长度。

一个非解决办法是的f的定义修改为:

f' :: (Int, Int) -> [a] -> [a] 
f' (2,_) = previous def 
f' (p,_) = previous def 

funcToLen :: ((Int, Int) -> [a] -> [a]) -> (Int, Int) -> Int 
funcToLen f' (p,_) = p-1 
funcToLen g (p,e) = p^(e-1) 

h' :: (Int, Int) -> ((Int, Int) -> [a] -> [a]) -> [a] -> [a] 
h' (p,e) func xs = let len = funcToLen func 
         func' = func (p,e) 
        in previous def 

-- usage 
(\p -> h' (p,??) f') 
(\(p,e) -> h' (p,e) g) 

这有几个缺点:

  • 我必须要改变的f第一个参数,然后忽略第二部分的元组
  • 当我实际使用h'f',我必须为元组的第二部分
  • 最重要的是,funcToLen不起作用,因为我无法对函数名称进行模式匹配。

,实际工作的另一种解决方案是使用Either

f' :: Int -> (Int, [a] -> [a]) 
f' 2 xs = (1, previous def) 
f' p xs = (p-1, previous def) 

g' :: (Int, Int) -> Either Int ([a] -> [a]) 
g' (p,1) xs = (1, previous def) 
g' (p,e) xs = (p^(e-1), previous def) 

h' :: (Int, ([a] -> [a])) -> ([a] -> [a]) 
h' ef = let len = fst ef 
      f = snd ef 
     in previous def 

这也有一些缺点:

  • 长度功能被复制为f'每个模式和g'
  • f'g'和h'的类型签名都是丑陋的
  • 我不能立即自己使用f'g'(即:不作为h'的参数)。相反,我必须剥离元组。

我正在寻找方法来清洁这件事让我没有到处复制长度的功能,也可以让我使用的功能fg'以预期的方式。我期望这个问题在之前已经“解决”了,但我不知道我应该在寻找什么。

+0

为什么你需要这些混乱的“长度来操作”呢?听起来好像分割列表并将某些部分传递给在列表上运行的函数会更好。 – leftaroundabout

+0

我很难理解你在问什么。在函数上不可能进行模式匹配,在funcToLen的定义中,第一个模式总是会成功的,在第二个例子中,您使用'Either'作为构造函数(你的意思是'Left'/'Right'?)无论哪种方式,都有很多随机的单字符变量存在,这很难遵循。我很难理解为什么这是必要的。无论如何,既然你有两种不同的类型,并且需要对它们进行模式匹配,使用'Either'似乎是最好的选择。 –

+0

@leftaroundabout总之,数学。列表输入是张量,“f”和“g”在该张量的一个维度上操作。函数“h”将“f”和“g”从一维提升到多维。其结果是'f'和'g'最终只能在列表的几个元素上工作,间隔一个步幅和一个偏移量。 'h'需要知道'f'的维数,以便知道运行'f'的次数(以及用什么步长/偏移量)。 – crockeea

回答

1

如果你创建一个函数c计算p^e-1,有效地fg去耦此操作:

c :: (Int, Int) -> Int 
c (p, e) = p^(e - 1) 

你可以(通过简单地删除g)合并fg到相同的功能。当您必须将元组转换为Int时,可以使用c

h的执行也很平凡,不包含重复的代码。

+0

我不能摆脱'g',它做的事情完全不同于'f'。也许你可以展示更多的代码? – crockeea