30

コードで型クラスを使用する場合と使用しない場合を理解するのが難しい場合があります。もちろん、独自の を作成し、既に定義されている型クラスを使用しないことを意味 します。例(非常にばかげた例)によって、私はすべきですか:

data Cars = Brakes | Wheels | Engine
data Computers = Processor | RAM | HardDrive  

class Repairable a where
    is_reparaible :: a -> Bool

instance Repairable Cars where
    is_repairable (Brakes) = True
    is_repairable (Wheels) = False
    is_repairable (Engine) = False

instance Repairable Computers where
    is_repairable (Processor) = False
    is_repairable (RAM)       = False
    is_repairable (HardDrive) = True

checkState :: (Reparaible a) => a -> ... 
checkState a = ...

(明らかに、これは愚かで不完全な例です)。

しかし、これは少しの使用のためにたくさんありますよね?新しいデータ型と型クラスを (それらのインスタンスと共に) 定義せずに関数を定義するだけの単純なことをすべきではないのはなぜですか。

この例は単純すぎるのですが、実際、関数を定義するだけでなく、github で Haskell コードを参照すると、そのようなもの (新しいデータ型 + 型クラス + インスタンス) をよく見かけます。

では、いつ新しいデータ型、型クラスなどを作成する必要があり、いつ関数を使用する必要がありますか?

ありがとう。

4

2 に答える 2

48

新しいデータ型と型クラスを (それらのインスタンスと共に) 定義せずに関数を定義するだけの単純なことをすべきではないのはなぜですか。

なぜですか?次のように定義できます。

checkState :: (a -> Bool) -> (a -> b) -> (a -> b) -> a -> b
checkState is_repairable repairs destroy a
    = if (is_repairable a) then repairs a else destroy a

人々は常に型クラスを誤用しています。それが慣用句であるという意味ではありません。

より一般的な質問に答えるために、型クラスを使用する場合と使用しない場合の経験則を次に示します。

次の場合は型クラスを使用します。

  • 特定のタイプごとに正しい動作は 1 つだけです

  • 型クラスには、すべてのインスタンスが満たさなければならない方程式 (つまり「法則」) が関連付けられています。

次の場合は型クラスを使用しないでください。

  • 名前空間のことだけをしようとしています。それがモジュールと名前空間の目的です。

  • 型クラスを使用する人は、インスタンスのソース コードを見ずに、型クラスがどのように動作するかについて推論することはできません。

  • 有効にしなければならない拡張機能が制御不能になっていることに気付きました

于 2013-06-14T02:07:16.327 に答える
6

多くの場合、型クラスの代わりにデータ型を使用できます。

data Repairable a = Repairable 
   { getRepairable :: a
   , isRepairable :: Bool
   , canBeRepairedWith :: [Tool] -> Bool  -- just to give an example of a function
   } 

もちろん、この値を明示的に渡す必要がありますが、複数の選択肢がある場合 (たとえば、可能な限り数値の s を考えSumてください)、これは良いことです。型クラスとほぼ同じ表現力を持っていることを除いて。ProductMonoid

于 2013-06-14T13:09:39.510 に答える