[英]A Haskell List Involving Recursion and High Order Functions
现在,我有了这段代码,它获取一个列表,并对第一个元素然后对其他每个元素进行处理。 并返回已转换元素的列表。 我遇到的问题是我想拥有一个包含未转换和已转换元素的列表。 这是我到目前为止的内容:
applyToEveryOther :: (a -> b) -> [a] -> [b]
applyToEveryOther _ [] = []
applyToEveryOther f [x] = [f x]
applyToEveryOther f (x:y:xs) = f x : y : applyToEveryOther f xs
它给我的错误表明函数的: y
部分存在问题
当我尝试您的代码时,出现以下(当然有些冗长和令人困惑的)错误消息:
EveryOther.hs:4:42: error:
• Couldn't match type ‘b’ with ‘a’
‘b’ is a rigid type variable bound by
the type signature for:
applyToEveryOther :: forall a b. (a -> b) -> [a] -> [b]
at EveryOther.hs:1:22
‘a’ is a rigid type variable bound by
the type signature for:
applyToEveryOther :: forall a b. (a -> b) -> [a] -> [b]
at EveryOther.hs:1:22
Expected type: [a]
Actual type: [b]
• In the second argument of ‘(:)’, namely ‘applyToEveryOther f xs’
In the second argument of ‘(:)’, namely
‘y : applyToEveryOther f xs’
In the expression: f x : y : applyToEveryOther f xs
• Relevant bindings include
xs :: [a] (bound at EveryOther.hs:4:26)
y :: a (bound at EveryOther.hs:4:24)
x :: a (bound at EveryOther.hs:4:22)
f :: a -> b (bound at EveryOther.hs:4:19)
applyToEveryOther :: (a -> b) -> [a] -> [b]
(bound at EveryOther.hs:2:1)
但是,值得尝试弄清楚GHC在这里所说的话。 根据第二个要点,GHC正在处理子表达式y : applyToEveryOther f xs
,并专门查看该表达式中:
运算符的第二个参数(即applyToEveryOther f xs
。它希望该表达式的类型为[a]
,但是表达式的实际类型是[b]
类型。
在此, a
和b
都是“刚性”类型,仅表示它们是由程序员明确指定的。 GHC在相关绑定中还指出y
类型为a
。
因此,总而言之,您要求GHC评估表达式:
y : applyToEveryOther f xs
您已经指定y
类型为a
且applyToEveryOther f xs
类型为[b]
,而GHC拒绝这样做,因为Haskell中的列表无法混合使用两种不同的类型。
这就是解决整个问题的关键。 你想改变你的一些的元素[a]
列表从a
到b
,但你要返回的混合列表a
S和b
秒。 Haskell无法做到这一点!
函数的唯一工作方式是更改签名,以使a
和b
为同一类型:
applyToEveryOther :: (a -> a) -> [a] -> [a]
并且您的代码可以正常工作。
您可以“发现”正确签名的另一种方法是将其遗漏,让Haskell推断出最通用的签名。 如果将代码(没有显式签名)加载到GHCi中并要求输入类型,则会得到:
> :t applyToEveryOther
applyToEveryOther :: (a -> a) -> [a] -> [a]
>
这是此功能最通用的类型。
如果我理解正确,那么您既需要原始值又需要转换后的值。
但是,评估applyToEveryOther (+3) [0,1,2]
返回[3,1,5]。 如果您想要[0,3,1,4,2,5]结果,请尝试
applyToEveryOther _ [] = []
applyToEveryOther f [x] = [x,f x]
applyToEveryOther f (x:xs) = x: f x : applyToEveryOther f xs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.