2016-04-28 71 views
1

我期待通过this介绍Haskell的包含这个例子:Haskell的类型声明多个参数功能

data Tree a    = Leaf a | Branch (Tree a) (Tree a) 

它说基本上还定义类型:

Branch     :: Tree a -> Tree a -> Tree a 
Leaf     :: a -> Tree a 

我明白Leaf的定义是说它将a映射到aTree。但我不明白的分公司定义,我把它读作“科地图aaTreeaTreeTree这听起来不正确的。这是因为所有的Haskell函数得到默认令行禁止?

回答

2

我把它读作“的一个分支地图树的树与树的”

你能想到的定义,需要一个Tree a并返回另一个功能,这也需要一个函数Tree a,并产生一个Tree a(这是最终的结果,一棵树有两个分支)。你的Branch签名相当于

Branch :: Tree a -> (Tree a -> Tree a) 

每个函数只有一个输入参数被称为currying概念。

2

Branch (Tree a) (Tree a)是具有两个类型参数,这两者都是Tree a一个构造,以及该构造的结果是一个Tree a,的

Tree a -> Tree a -> Tree a 
因此定义

我明白叶定义是说它将a映射到a的树上。但我不明白的分公司定义,它不应该是这样的:

Branch :: (Tree a, Tree a) -> Tree a 

没有,因为如果你使用(Tree a, Tree a),你会定义一个单一类型的参数,它是一个元组。

+0

在这两种情况下都有一个_type_参数:'a'。 –

4

号如果有一个像签名:

Branch :: (Tree a, Tree a) -> Tree a 

那么你应该给它一个元组,并调用类的构造函数:但是

Branch (tree1,tree2) 

Branch有一个签名:

Branch :: Tree a -> Tree a -> Tree a 

或带明确的括号:

Branch :: Tree a -> (Tree a -> Tree a) 

所以,当你喂Branch第一参数,如Branch tree1,签名是:

(Branch t1) :: Tree a -> Tree a 

当你终于给它第二个参数t2,其类型会崩溃到:

((Branch t1) t2) :: Tree a 

一个更方便的例子是,例如(+) whic h不是一个构造函数,而是一个函数。 (+)我们(+)具有签名

(+) :: Int -> Int -> Int 

(Haskells加上是更通用一些,但我们不要考虑这个了)。

如果您写信(5+)你有专门的函数的函数:

(5+) :: Int -> Int 

换句话说,你构建的功能,将增加5为给定数。


由于签名(a,b) -> ca -> b -> c是却丝毫等同,哈斯克尔提供curryuncurry功能:如果你决定你需要例如用于Branch这应该是一个额外的构造

curry :: ((a, b) -> c) -> a -> b -> c 
uncurry :: (a -> b -> c) -> ((a, b) -> c) 

喂一个元组,你可以构造这样的构造函数:

branchTuple :: (Tree a, Tree a) -> Tree a 
branchTuple = uncurry Branch