理解Haskell类型签名(例如zipWith with(+;))
我有一个关于Haskell中的类型签名的问题,我发现有时候有点难以理解。例如,理解Haskell类型签名(例如zipWith with(+;)),haskell,signature,type-signature,Haskell,Signature,Type Signature,我有一个关于Haskell中的类型签名的问题,我发现有时候有点难以理解。例如,zipWith的类型签名为: zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 我在这里看到的是zipWith需要一个函数(参数类型为a和b),一个带有as的列表,一个带有bs的列表,它给我们一个cs的列表。但是我不明白为什么我可以将zipWith与(+)一起使用,例如,它有以下签名: (+) :: a -> a -> a zipW
zipWith
的类型签名为:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
我在这里看到的是zipWith
需要一个函数(参数类型为a
和b
),一个带有a
s的列表,一个带有b
s的列表,它给我们一个c
s的列表。但是我不明白为什么我可以将zipWith
与(+)
一起使用,例如,它有以下签名:
(+) :: a -> a -> a
zipWith' :: (a -> a -> a) -> [a] -> [a] -> [a]
在我看来,(+)
的签名与(a->b->c)
的签名不匹配<代码>(+)只需要类型a
的参数,而(a->b->c)
需要不同类型的参数:a
和b
。谁能给我一个提示,我的错在哪里?(a->b->c)
表示任何函数,它接受类型a
和类型b
,并返回类型c
。
没有什么可以阻止您使用签名为(a->a->a)
的函数,只是在这种情况下,类型都是相同的
假设您有一个具有此签名的方法:
(+) :: a -> a -> a
zipWith' :: (a -> a -> a) -> [a] -> [a] -> [a]
在这种情况下,您不能使用签名为
(a->b->c)
的方法,因为预期的方法签名更严格。啊,我明白了。因此,当我在函数签名中使用不同的类型参数时,所有类型都可以是相同的。但是在类型签名中,如(a->a->a)1。参数必须具有与2相同的类型。参数,对吗?你的第一句话有点误导;对于(对于所有a b c.(a->b->c))
,这是正确的,但该类型不会出现在带有签名的Zipw中。@Meiner-正确。换句话说,a->a->a
是a->b->c
的一个特殊实例,其中b
恰好与a
相同,c
。这个过程的术语是统一。这个术语实际上更一般;在类型推断的上下文中,这就是为什么a
可以匹配Int
,或者[a]->b
可以匹配[Bool]->[Char]->[Int->Int]
。另一种看待zipWith
函数的方法是它“提升”由于签名可以写成zipWith::(a->b->c)->([a]->[b]->[c])
,因此列表monad有两个参数的函数。在(+)::Int->Int->Int
,a~Int
,b~Int
和c~Int
的情况下,因此zipWith(+)::[Int]->[Int]->[Int]
。