haskell 给定类型签名的函数处理列表
haskell function given type signature dealing with list
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
给定此类型签名,mapNew
应该是哪种函数?
我知道 return 类型是列表。
这看起来很像作业题。如果是,我强烈建议您尝试自己回答这个问题。话虽如此,我将向您介绍我将如何制定这个问题的答案,并希望能让您深入了解应该如何处理此类问题。
我们知道 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
并且需要始终将它传递给 bs
中每个元素 b
的 f
,我们可以为 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
大多数 haskell 程序员会将此定义简化为:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = map (f a) bs
因为 (f a)
恰好是部分应用的函数 fa
。此外,我们可以 eta-reduce 这个表达式为:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f = map (f a)
这个答案的关键在于语句"Knowing that we only have a single a
and need to always pass it to f
for each element b
in bs
"。我怎么知道的?
由于参数多态性,我们无法检查 a
类型的任何值。这意味着我们可用的类型 a
的唯一值是传递给 mapNew
的值。此外,由于 f
采用单个 b
并生成单个 c
,我们知道必须首先从提供的列表中获取 b
才能应用 f
给它。这正是 map
所做的,通过将 f
部分应用到 a
,我们得到了我们想要传递给 map
.
的第一个参数
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
给定此类型签名,mapNew
应该是哪种函数?
我知道 return 类型是列表。
这看起来很像作业题。如果是,我强烈建议您尝试自己回答这个问题。话虽如此,我将向您介绍我将如何制定这个问题的答案,并希望能让您深入了解应该如何处理此类问题。
我们知道 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
并且需要始终将它传递给 bs
中每个元素 b
的 f
,我们可以为 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
大多数 haskell 程序员会将此定义简化为:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = map (f a) bs
因为 (f a)
恰好是部分应用的函数 fa
。此外,我们可以 eta-reduce 这个表达式为:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f = map (f a)
这个答案的关键在于语句"Knowing that we only have a single a
and need to always pass it to f
for each element b
in bs
"。我怎么知道的?
由于参数多态性,我们无法检查 a
类型的任何值。这意味着我们可用的类型 a
的唯一值是传递给 mapNew
的值。此外,由于 f
采用单个 b
并生成单个 c
,我们知道必须首先从提供的列表中获取 b
才能应用 f
给它。这正是 map
所做的,通过将 f
部分应用到 a
,我们得到了我们想要传递给 map
.