haskell函数声明

时间:2011-02-22 01:07:16

标签: haskell

我一直在玩haskell,我发现如果我在代码文件中编写以下函数:

f :: Int -> [a] -> a
f idx str = last $ (take . succ) idx str

然后这完全没问题。当然,我认为没有参数,代码看起来会更好。

f :: Int -> [a] -> a
f = last $ (take . succ)

但是当我尝试将其加载到gchi中时会产生错误

Couldn't match expected type `[a]'
       against inferred type `Int -> [a1] -> [a1]'
In the second argument of `($)', namely `(take . succ)'
In the expression: last $ (take . succ)
In the definition of `f': f = last $ (take . succ)

失败,模块加载:无。

我对如何发生这种情况感到困惑......

3 个答案:

答案 0 :(得分:10)

你误解了优先权。这样:

f idx str = last $ (take . succ) idx str

解析如下:

f idx str = last $ ( (take . succ) idx str )

不是(如您所愿)这样:

f idx str = ( last $ (take . succ) ) idx str

$具有极高的任何运算符的最低优先级,函数调用具有极高的优先级。 .具有第二高,因此(take . succ)在绑定到idx str之前绑定它的参数(last $)。

此外,该函数(编译时)不会像您希望的那样执行。它递增idx,然后从字符串中获取该字符。如果这是您想要的,为什么在succ工作时使用(+1)?您已经将类型限制为整数。

如上所述,您的函数与!!运算符相同 - 它只是一个数组索引函数。这是你想要的吗?或者您想要succ给定索引处的项目?您可以通过以下方式实现这一目标:

f :: Enum a => Int -> [a] -> a
f idx str = succ $ str !! idx
-- or
f idx str = succ $ (!!) str idx
-- or, only one argument
f idx = succ . (!! idx)

我还在研究一个没有书面论据的版本。编写工作代码可能更重要吗? ;)

答案 1 :(得分:6)

当您尝试使用last

撰写(take . succ)时会发生这种情况
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

last :: [t] -> t  ~ (b -> c)  
-- so b ~ [t] and c ~ t   

(take . succ) :: Int -> [t] -> [t]  
-- so a ~ int and b ~ [t] -> [t]  

b的类型被推断为来自[t]的{​​{1}},但它与last(take . succ)

中的b类型无法匹配

答案 2 :(得分:5)

f idx str = last $ (take . succ) idx str
-- applying definition of ($)
f idx str = last ((take . succ) idx str)
-- adding parentheses for clarity
f idx str = last (((take . succ) idx) str)
-- using definition of (.)
f idx str = (last . (take . succ) idx) str
-- η-conversion
f idx = last . (take . succ) idx
-- infix to prefix notation
f idx = (.) last ((take . succ) idx)
-- ading parentheses for clarity
f idx = ((.) last) ((take . succ) idx)
-- using definition of (.)
f idx = ((.) last . (take . succ)) idx
-- η-conversion
f = (.) last . (take . succ)
-- remove parentheses: (.) is right-associative
f = (.) last . take . succ