2017-12-05 21 views
3

私はhaskellを初めて使っています。このタイプのシグネチャと呼ばれるものについていくつか読んでいますが、理解できないことがいくつかあります。ここでHaskellタイプシグネチャ

はコードがで探していますされています。だから、

--mult applies product 
mult :: Num a => [a] -> a 
mult = foldr (*) 1 

--posList filters positive numbers out 
posList :: (Ord a, Num a) => [a] -> [a] 
posList = filter (>0) 

--trueList determines whether all of the members of a list are T or not 
trueList :: [Bool] -> Bool 
trueList = foldr(&&) True 

--evenList determines where all of the members of a list are even or not 
evenList :: (Integral a, Foldable t) => t a -> Bool 
evenList x = if (((foldr (+) 2 x) `mod` 2) == 0) then True else False 

、私はあなたが別の方法で簡単にこれらの機能を行うことができます知っているが、私は高階関数mapfilterfoldrを使用するための割り当てを持っていました私はそのようにしなければなりませんでした。とにかく、私はそれらを書いた人であるので、機能の仕組みを理解しています。それらの用語は理解できません。IntegralFoldable、どういう意味ですか?彼らはハスケルの面で何と呼ばれていますか?

+3

あなたは 'evenList'をテストしましたか? 'evenList [1,3]'を試してみることをお勧めします。 – chi

+1

IntegralとFoldableは、このタイプのクラス*、googleです。基本的に「Foldable」は「tはリストのようなタイプ」を意味します。 –

+0

タイプクラスは、Haskellでオーバーロードがどのように行われるかです。型は、いくつかの関数を実装することによって型クラスを実装します。例えば、 '(+)'の型は 'Num a => a - > a - > a'なので、私が追加したい型' Foo'を定義するなら、 '(+ ):: Foo - > Foo - > Foo '' Foo'を使って 'Num'クラスをインスタンス化することでしかできません –

答えて

5

これらは、多型式に対する制限である。である。

静的に型付けされているにもかかわらず、parametric polymorphismというシステムでは、さまざまな型で動作する関数を作成するのが非常に簡単です。

mult :: [Integer] -> Integer 
mult = foldl' (*) 1 -- foldl' is better for performance/memory than foldr 

posList :: [Integer] -> [Integer] 
posList = filter (>0) 

trueList :: [Bool] -> Bool 
trueList = foldl' (&&) True 

evenList :: [Integer] -> Bool 
evenList x = foldl' (+) 2 x `mod` 2 == 0 
      -- `if True then True else False` is tautological 

これらの署名の仕事のすべて(改善実装とし、元のものとの両方):私は、最初の代わりにシグネチャすべての機能に(単相)のコンクリートを与えるでしょう。

しかし、のみIntegerのリストで動作します。それは必ずしも十分に一般的ではありません。たとえば、分数のリストの積を計算することは完全に合理的です。しかし、単形署名の場合、mult [1.5, 2.4, 20]は機能しません。これらの数字はIntegerと互換性がありません。関数を整数に制限したくない場合は、任意の数値型を扱い、常に要素と同じ型の結果を得るだけです。つまり、あなたは基本的に署名

mult :: ∀ a . [a] -> a 

が...すべてのタイプaのために」をお読みになりたい、機能multは、要素タイプaを持つリストを取り、その結果、単一a - 値を与えるザあなたは、このようなタイプの変数を持っている場合は、あなたが同様の機能が要素を乗算することができなければならないので、それは

mult :: [a] -> a 

、しかしまだ動作していないことを作ることができる、つまり、Haskellでは暗黙的である。しかし、それは可能ではありませんすべてタイプ、number typesのみ。署名は、本質的に

posList :: [a] -> [a] 

ですが、あなたはまた、0と(Ord)要素を比較できるようにする必要があります(Numを):したがって、あなたはそれがはるかに同じことだposListについて制約

mult :: Num a => [a] -> a 

を追加します。したがってevenListの場合

posList :: (Num a, Ord a) => [a] -> [a] 

制約は、数値演算は(+)(==)及びmodです。だから、原則的に、私たちはNumEqIntegralが必要ですが、十分であるだけではなるように、とにかくNumEqとしてスーパーIntegralあります

evenList :: Integral a => [a] -> Bool 

...しかし、まだ最も一般的な形式ではありませんています。あなたは折り畳みでそのリストを減らしますが、折り畳むことができるのはリストだけではありません。たとえば、配列、マップ、およびMaybeの値を折り畳むこともできます。折りたたむことができるすべてのコンテナの型クラスが呼び出されますが、あなたはそれを推測しません。Foldableだから我々はあなたがmulttrueListに同じ一般化を適用することができ

evenList :: (Integral a, Foldable t) => t a -> Bool 

で終わる:

mult :: (Num a, Foldable t) => t a -> a 
trueList :: Foldable t => t Bool -> Bool 
+0

ありがとう! –