我一直在使用 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)
失败,已加载模块:无。
我有点困惑这怎么会发生......
最佳答案
您误解了优先级。这:
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)
在绑定(bind)到 last $ 之前先绑定(bind)到它的参数 (
.idx str
)
此外,该函数(在编译时)不会执行您希望它执行的操作。它递增 idx,然后从字符串中获取该字符。如果这就是您想要的,那么当 (+1)
有效时为什么要使用 succ
呢?您已经将类型限制为整数。
正如所写,您的函数与 !!
运算符相同 - 它只是一个数组索引函数。这是你想要的吗?或者您想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)
我仍在开发一个没有书面参数的版本。也许编写工作代码更重要? ;)
关于Haskell 函数声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5073058/