haskell函数声明

chu*_*lor 6 haskell

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

f :: Int -> [a] -> a
f idx str = last $ (take . succ) idx str
Run Code Online (Sandbox Code Playgroud)

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

f :: Int -> [a] -> a
f = last $ (take . succ)
Run Code Online (Sandbox Code Playgroud)

但是当我尝试将其加载到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)
Run Code Online (Sandbox Code Playgroud)

失败,模块加载:无.

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

Chr*_*utz 10

你误解了优先权.这个:

f idx str = last $ (take . succ) idx str
Run Code Online (Sandbox Code Playgroud)

解析如下:

f idx str = last $ ( (take . succ) idx str )
Run Code Online (Sandbox Code Playgroud)

不(如你所愿)像这样:

f idx str = ( last $ (take . succ) ) idx str
Run Code Online (Sandbox Code Playgroud)

$具有极高的任何运算符的最低优先级,并且函数调用具有极高的优先级..具有第二高,因此在它绑定之前绑定(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)
Run Code Online (Sandbox Code Playgroud)

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


kef*_*hou 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]  
Run Code Online (Sandbox Code Playgroud)

B的类型推断是[t]last,但它不能对阵B的类型,(take . succ)这是[t] -> [t]


eph*_*ent 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
Run Code Online (Sandbox Code Playgroud)