2017-07-30 6 views

答えて

6

タイプクォーターは、型(文字通りタイプのグループです)に関する一般的な方法を提供します。あなたはこのように、明示的な型Integerするのではなく、型クラス制約を使用することができます。

myFunc :: Integral a => [a] -> String 
myFunc x = if (even (sum x)) then "even" else "odd" 

これはそれがaは型変数である[a]からStringの機能だし、いずれかのように制約されているように指定されたでしょうそれがIntegral typeclassのメンバーである限り、タイプします。これを言うもう1つの方法は、Integral型の場合のインスタンスがである限り、どのタイプでもあります。つまり、その特定の型に対して指定された型クラスのメソッドがあることを意味します。

Integral typeclassは、値が整数(つまり積分)の型のためのものです。

幸いなことに、IntIntegerのインスタンスはIntegralに提供されていますので、それを使用できます。

+0

ありがとうございます。 –

3

Int型と整数型は異なる型です。しかし、それらはどちらもIntegral型クラスのインスタンスですが、関数の1つとして 'mod'があります。

あなたの関数が特定の型以外のもので動作するようにするには、[Integer] - [Char]または[Int] - [ Char]の場合、型はそれらのうちの1つよりも制限が少ないはずです。それは[a] - > [Char]でなければなりません。しかし、あなたがそのインスタンスを宣言した場合、それは2つの理由のためにコンパイルされません:

1)合計はxの数値のリストを必要とします。すなわち、

sum :: Num a => [a] -> a; 

民は、とりわけ、民to include a definition for (+)のインスタンスである任意の種類を必要とする別の型クラスです。これにより合計で加算を使用してすべての数値を加算することができます。

2)modは、xの合計がIntegralのインスタンスである必要があります。だから、

mod (sum x) :: Integral a => a -> a 

技術的にもタイプが合計はXでなければならないため、のNumのインスタンスですが、definition of Integralも順番になるためにそれを必要と実のインスタンスであることを積分の任意のインスタンスを必要とすることが必須ですタイプNumの - 基本的にあなたは、インスタンスNumberがフリーのタイプである必要があります。

だから、最後に、あなたは最初のタイプは、(実際にそれのための用語を知らない)タイプ「変数」であることができるようにする必要がありますが、必要とされる1は、インテグラル型である:

myFunc :: Integral a => [a] -> [Char] 
myFunc x = if (sum x `mod` 2 ==1) then "odd" else "even" 

また、型宣言(myFunc :: Integral a => [a] - > [Char])を含めないと、コンパイラはこれをすべて仮定して空白を自動的に埋めます君は。型宣言は、関数の型を明確にするか、関数の適用可能性を制限するか、何らかの理由で型を推論できないときに変数の型をコンパイラに明確にするために使用されます。しかし、あなたがしたくない場合は、通常、型を宣言する必要はありません。

+1

ありがとう、それは動作します。 –

+2

'Integral'は型ではなく、typeclassです。これはここでかなり重要なことです。 –

+1

@ReinHenrichsはい、私の間違いは、それを修正しました。 –

関連する問題