2017-03-28 8 views
0

私は、次のタイプがあります:私は、人のインスタンスへの傷害を持ち上げる機能を作成しようとしているレコード構文を使用してデータコンストラクタに持ち上げる?

data Person a = {name :: String, age :: Int, injury :: Injury a} 

data Injury a = Physical a | Mental a 

を:

liftInjury :: Person a -> Injury a -> Person a 
liftInjury person inj = person {injury = int} 

class Hospital i where 
    admit :: Person a -> i -> Person a 

instance Hospital (Injury a) where 
    admin person inj = liftInjury person inj -- ERROR 

がエラー:

Couldn't match type ‘a’ with ‘a1’ 
    ‘a’ is a rigid type variable bound by 
    the instance declaration 

コンパイラがaが拒否されたことをliftInjuryがのaと同じであることがわからないために発生していますか?

これに最適な解決策は何ですか?

+0

私はあなたの病院のクラスで機能的な依存関係のようなものを使うことができると思います。しかし今は完全な答えを書く時間がありません – epsilonhalbe

+0

なぜ「病院」はクラスである必要がありますか? –

+0

@BenjaminHodgson複数のデータ型を扱えるようにするためには、関数が必要です.. '傷害a'、'複雑化a'など... –

答えて

1

あなたはPersonの種類とInjuryのタイプの両方に制約を置くことができるようになるマルチパラメータ型クラス、でこれを解決することができます:

Personの型パラメータを追加する
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances #-} 

class Hospital i p where 
    admit :: Person p -> i -> Person p 

instance Hospital (Injury a) a where 
    admit person inj = liftInjury person inj 

をクラス定義によって、instance宣言内に制約を置くことができます。PersonInjuryの型パラメータが同じであることを確認できます。

シンプルなオプションではなく、傷害のタイプ自体の損傷の型パラメータを取るためにHospitalを変更するには、次のようになります。

class Hospital a where 
    admit :: Person a -> Injury a -> Person a 

...しかし、私はあなたのシステムの残りの部分は、そのオプションを排除想像してみてください。

+0

完璧、これはありがとう –

関連する問題