mapNew :: a -> (a -> b -> c) -> [b] -> [c]
鉴于此类型签名,mapNew
应该是什么类型的函数?
我知道返回类型是列表。
答案 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
的第一个参数。