繁体   English   中英

包含递归和高阶函数的Haskell列表

[英]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]类型。

在此, ab都是“刚性”类型,仅表示它们是由程序员明确指定的。 GHC在相关绑定中还指出y类型为a

因此,总而言之,您要求GHC评估表达式:

y : applyToEveryOther f xs

您已经指定y类型为aapplyToEveryOther f xs类型为[b] ,而GHC拒绝这样做,因为Haskell中的列表无法混合使用两种不同的类型。

这就是解决整个问题的关键。 你想改变你的一些的元素[a]列表从ab ,但你要返回的混合列表a S和b秒。 Haskell无法做到这一点!

函数的唯一工作方式是更改签名,以使ab为同一类型:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM