haskell 将字母添加到列表(多态函数)

vfh0ocws  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(119)

我是Haskell的初学者,我有一个练习,其中的想法是制作多态函数。
我想做一个函数,它接受列表和另一个参数,添加到列表中。

addA :: a -> [a] -> [a]
addA [] = []
addA (x: xs) = x + a : addA xs

在最后一行中,有一个错误显示:声明变量a不在作用域中,并且->

Couldn't match expected type: [a1]
              with actual type: [[a1]] -> [[a1]]
• Probable cause: ‘addA’ is applied to too few arguments
  In the second argument of ‘(:)’, namely ‘addA xs’
  In the expression: x + a : addA xs
  In an equation for ‘addA’: addA (x : xs) = x + a : addA xs
• Relevant bindings include
    xs :: [a1]

我不知道如何在列表中的每个元素中添加输入。

trnvg8h3

trnvg8h31#

当你使用没有任何高级语言扩展的普通Haskell时,编译器能够从表达式中推断出函数的类型。因此,类型注解实际上是可选的。
然后,考虑函数定义 * 没有 * 类型注解:

addA [] = []
addA (x: xs) = x + a : addA xs

在这种情况下,编译器错误是 still

error: Variable not in scope: a

你现在明白为什么了吗?

bz4sfanl

bz4sfanl2#

让我们看看addA的签名是什么:

addA :: a -> [a] -> [a]

这意味着为了调用addA,您需要提供 * 两个 * 参数。
然而,在你的定义中:

addA [] = [] -- There is only one parameter specified on the left side of '=', i.e. []
addA (x: xs) = x + a : addA xs -- There is only one parameter specified on the left side of '=', i.e. (x:xs)

这就是编译器所抱怨的。
如果你不确定如何正确地实现算法,但想通过类型检查,你可以使用丢弃模式(_):

addA _ [] = []
addA _ (x: xs) = x + a : addA xs -- This still would not compile, but is caused by the fact that 'a' is not in scope in your implementation

话虽如此,由于问题是要求一个多态实现,我能想到的最多态的实现是这样的:

addA :: (Functor f, Num a) => a -> f a -> f a
addA = fmap . (+)

这是多态的,因为它适用于任何数值类型aIntDouble等)和任何函子类型f[]MaybeEither等),因此:

addA 2 [1, 2] -- returns [3, 4]
addA 3.0 (Just 3.0) -- returns Just 6.0
addA 7 (2, 5) -- returns (2, 12)

相关问题