我正在为考试而学习,对此功能感到困惑。基于输出,我如何知道该函数的类型声明为(a-> b-> c)?另外,我如何评估我的功能?
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
我了解的是,haskell中的高阶函数意味着它们将一个函数作为参数并返回一个函数,对吗?我怎么称呼这个特殊的功能?
我这样做:
zipWith' [1..5] ['a','z','r']
但是我知道是错误的,因为我将其称为常规zip
函数,它接受2个列表并返回一个元组。我只是对类型声明感到困惑
zipWith' :: [a] -> [b] -> [(a,b)]
答案 0 :(得分:3)
对于此答案,我们将承认所有函数均已使用。也就是说,每个函数都有类型a -> b
,其中a
和b
是某种类型。
一个高阶函数是其类型包括用于 其自变量或返回类型的函数的函数。返回值很简单:这是您通常认为带有多个参数的任何函数:
take :: Int -> [a] -> [a]
。它需要一个Int
并返回一个(多态的)函数,该函数需要一个列表并返回一个列表。
map :: (a -> b) -> [a] -> [b]
。它需要一个函数(字面上是 any 函数),并从列表到列表返回一个函数。返回值的类型取决于参数的类型。
采用函数并返回非函数值的高阶函数实际上很少见。也许评论者会指出一个明显的我正在忽略的评论者,但在此之前,请考虑使用fix :: (a -> a) -> a
。
现在,zipWith'
是一个高阶函数的示例,其参数 itself 必须是一个高阶函数。普通类型a -> b
可以与ord :: Char -> Int
(a ~ Char
和b ~ Int
)这样的普通函数以及(+)
这样的高阶函数({ {1}}和a ~ Num t => t
。类型b ~ Num t => t -> t
将仅与高阶函数统一。a -> b -> c
可能是也可能不是函数类型,但是{ {1}}是显式函数类型。
这意味着一旦将a
应用于某些高阶函数,类型推断就为您提供有关b -> c
,zipWith'
和[a]
的类型的更多信息。必须在结果函数中。
[b]
告诉您[c]
。zipWith' (+)
告诉您a ~ b ~ c ~ Num t => [t]
和zipWith' (,)
仍然不受限制,但是a
b
告诉您c ~ (a, b)
不受限制,但zipWith' (:)
。如果您认为可以将a
定义为b ~ c ~ [a]
,这可能也会有所帮助。