我一直在尝试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)失败,模块已加载:无。
我有点困惑这是怎么发生的.
发布于 2011-02-22 09:35:18
这就是尝试用(take . succ)合成last时会发生的情况
: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的类型从last推断为[t],但它与(take . succ)中的b的类型[t] -> [t]不匹配
发布于 2011-02-22 09:13:54
你误解了优先顺序。这一点:
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)在绑定到last $之前先绑定到它的参数(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)我仍在开发一个没有书面参数的版本。也许编写工作代码更重要?;)
发布于 2011-02-22 10:36:29
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 . succhttps://stackoverflow.com/questions/5073058
复制相似问题