我正在审查 Haskell:函数式编程工艺,但第356页上的类型签名已经让我进行了循环。
这是一个简单的:
succeed :: b -> Parse a b
succeed val inp = [( val, inp )]
如果<{1}},那该怎么办?{/ p>
b -> Parse a b
和
succeed Int -> Int
succeed a = a
你的参数量必须在类型声明中吗?如果您的类型声明只有一个类型变量,那么如何使用succeed Int -> Int -> Int
succeed a b = a + b
和val
:imp
应该读取,取一个succeed :: b -> Parse a b
类型的变量并返回一个类型a
,不取两个变量......允许Parse a b
在哪里?
答案 0 :(得分:8)
因为Parse
是其扩展中->
的类型同义词。例如:
type Foo = Int -> Int
succeed :: Int -> Foo
succeed a b = a + b
答案 1 :(得分:1)
在Haskell中,所有函数只接受一个参数并产生一个结果。如果类型为a -> b -> c
,则与a -> (b -> c)
相同。因此,实际上有一个函数,当给定一个参数产生另一个接受第二个参数并产生最终结果的函数时,而不是一个双参数函数。
将函数应用于两个参数时,例如f x y
,它与(f x) y
相同。您实际上是将f x
的结果应用于第二个参数y
。从这种行为中,您可以免费获得“部分申请”。
Prelude中有一对名为curry
和uncurry
的函数,可以让您在以此样式编写的函数和将两个参数直接作为一对的函数之间进行转换:
uncurry :: (a -> b -> c) -> ((a,b) -> c)
curry :: ((a,b) -> c) -> (a -> b -> c)
f :: a -> b -> c
f = ...
f' :: (a,b) -> c
f' = uncurry f
我不知道Parse
是如何定义的,但是如果你将它定义为函数类型的同义词(解析器常见的东西),你会得到那种行为。