2016-04-28 24 views
1

私はこの例が含まれているHaskellのにthis導入を通じて探しています:Haskellの型宣言

それは本質的にもタイプを定義していると言う
data Tree a    = Leaf a | Branch (Tree a) (Tree a) 

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

は、私が理解してLeafの定義は、aTreeに、aにマッピングしていると言っています。しかし、私は支店の定義を理解していない、私は正しい音ではありませんaTreeaTreeに「支部マップとしてaTreeをそれを読む。すべてのHaskellの関数は、デフォルトではカレーを受けるため、このですか?

答えて

2

私はあなたがまたAとる、Tree aを取り、別の関数を返す関数として定義と考えることができ

「の木の木の枝マップの木」としてそれを読みますTree aとなり、Tree aが生成されます(最終結果では、2つのブランチを持つツリー)。 Branchのあなたの署名が

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

すべての機能がcurryingと呼ばれているだけで1つの入力パラメータを持つという概念に相当します。

2

Branch (Tree a) (Tree a)Tree a共にする2つの型パラメータを持つコンストラクタで、そのコンストラクタの結果はTree a

Tree a -> Tree a -> Tree a 
の故に定義であります

リーフの定義はaをaのツリーに写像すると言っています。あなたが(Tree a, Tree a)を使用した場合、あなたはタプルで、単一の型パラメータを定義することになるので、

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

ありません:私は支店の定義を理解しない、それはのようなものであってはなりません。それはのような署名を持っていた場合

+0

両方の場合に1つの_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 tree1のような最初のパラメータ、Branchを養うときに、シグネチャは次のとおりです。

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

あなたが最終的にそれを二番目のパラメータt2を供給する場合、その型はに崩壊する:

((Branch t1) t2) :: Tree a 

さらに便利な例は、たとえば(+)です。 hはコンストラクタではなく関数です。 (+)当社プラス(+)は、署名に

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

(Haskellsをプラスもう少し汎用的ですが、今度はこれを考慮しないようにしましょう)があります。

あなたが今(5+)を書く場合は、関数にあなたの機能を専門にしている。言い換えれば

(5+) :: Int -> Int 

あなたが与えられた数に5を追加します新しい機能を構築しました。


(a,b) -> ca -> b -> cのための署名がしかし、ビットの同等なので、Haskellは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