haskell函数给出类型签名处理列表

时间:2015-02-15 20:26:35

标签: haskell

mapNew :: a -> (a -> b -> c) -> [b] -> [c]

鉴于此类型签名,mapNew应该是什么类型的函数?

我知道返回类型是列表。

1 个答案:

答案 0 :(得分:5)

这看起来很像一个家庭作业问题。如果是,我强烈建议您尝试自己回答这个问题。话虽如此,我将引导您完成如何制定这个问题的答案,并希望能够让您深入了解如何处理这样的问题。

我们知道mapNew的类型为a -> (a -> b -> c) -> [b] -> [c]。这看起来很像现有的Prelude函数map :: (a -> b) -> [a] -> [b]。所以我们可能想用map来写答案。

mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = ...

我们总是首先用函数写出函数,以便我们可以看到我们必须使用哪些部分。知道我们只有一个a,并且需要始终将f传递给b中的每个元素bs,我们可以为where添加mapNew :: a -> (a -> b -> c) -> [b] -> [c] mapNew a f bs = ... where fa :: b -> c fa = f a 子句这部分申请:

map

鉴于此,我们现在可以用mapNew :: a -> (a -> b -> c) -> [b] -> [c] mapNew a f bs = map fa bs where fa :: b -> c fa = f a 来表达我们的答案。

mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = map (f a) bs

大多数haskell程序员会将此定义简化为:

(f a)

因为fa正是部分应用的函数mapNew :: a -> (a -> b -> c) -> [b] -> [c] mapNew a f = map (f a) 。此外,我们可以将此表达式简化为:

a

这个答案的关键在于声明"知道我们只有一个f,并且需要始终将b传递给bs {} {1}}&#34 ;.我怎么知道这个?

由于参数多态性,我们无法检查a类型的任何值。这意味着我们可以使用的a类型的唯一值是传递给mapNew的值。此外,由于f只生成一个b并生成一个c,因此我们知道必须首先从提供的列表中获取b才能应用f 1}}到它。这正是map所做的,通过将f部分应用于a,我们得到了我们想要传递给map的第一个参数。