我有以下类型签名:
*Main Lib> let f :: a -> a -> a -> a; f = undefined
*Main Lib> let x :: Char; x = undefined
所以要找出,我会得到哪种结果类型,我做了:
*Main Lib> :t f x
f x :: Char -> Char -> Char
为什么不
Char -> Char -> Char -> Char
由于第一个参数已经替换为x
?
答案 0 :(得分:3)
是的,确切地说。考虑一个不同的函数length :: [a] -> Int
。如果您要求length "abc"
的类型,则会获得Int
:
Prelude> :t length "foo"
length "foo" :: Int
通常,如果您有一个函数f :: A -> B
和一个参数x :: A
,那么f x :: B
。
在您的情况下,我们有f :: a -> (a -> a -> a)
(专门针对a = Char
),因此A = Char
和B = Char -> Char -> Char
。
(a -> a -> a -> a
与a -> (a -> a -> a)
相同,因为类型中的->
是右关联的。)
答案 1 :(得分:2)
这是因为f x
是函数f
,其第一个参数已经应用,因此只需要两个来获取结果。这称为 currying 。
在Haskell中,实际上没有任何具有三个参数的函数。 a -> a -> a -> a
表示“一个函数,它接受a
并返回一个函数,该函数接受a
并返回一个函数,该函数接受a
并返回a
”
写出来很多,所以只要把一些parens放进去就会更清楚:a -> (a -> (a -> a))
。
因此f x
会为您提供a -> (a -> a)
。事实上,Haskell的语法允许你说f x y z
并且表现得就像你正在调用一个带有三个参数的函数,并且编译器足够聪明,在不需要时不构造所有那些中间curried函数。