エラーメッセージに示された2種類があり:*
は、Int
とBool
などの値が生息しているタイプの一種である、* -> *
タイプの一種である一方コンストラクタようMaybe
、[]
、及びIO
として。型コンストラクタは型レベル関数と考えることができます。Maybe
は、引数として型(型が*
)をとり、結果として型(種類も*
)を返します(例:Maybe Int :: *
)。種類は関数と同じ方法でカレー化されています。それは一種*
の種類を生成するために種類*
の二つの引数を取りますので、例えば、Either
は親切* -> * -> *
があります
Either :: * -> * -> *
Either Int :: * -> *
Either Int Bool :: *
ので誤差はごShow
インスタンスの型クラス制約から来ている:
instance (Show m, Show r) => Show (Thread m r) where
------
Show
は、表示できる種類の種類が*
の種類です。あなたはGHCiの中:kind Show
(または:k Show
)を入力することで、これを見ることができます:
> :kind Show
Show :: * -> Constraint
のでShow
は親切*
の種類を取り、型クラス制約を返します。制約に関する詳細があまりにも多くない場合、Show m
はそれがm :: *
を意味することを意味します。ただし、Thread
の定義では、の引数がAtomic
コンストラクタの定義に渡されます。このコンストラクタのフィールドの型は、m (Thread m r)
です。
> :kind Thread
Thread :: (* -> *) -> * -> *
ので、そのm :: * -> *
、不一致を意味します:Thread
のようなものを見てください。あなたが複数のフィールドに一致するパターンを提供してきました。ここ
show (Atomic m x) = "Atomic " ++ show m ++ " " ++ show x
- ----------------
が、Atomic
は一つだけのフィールドがあります。
次のエラーはつまり、あなたのShow
インスタンスの実装です。あなたは、次の実装を変更する必要があります
show (Atomic m) = "Atomic " ++ show m
あなたがShow m
制約を削除した場合、あなたはより多くの有益なエラーメッセージが表示されます:
Could not deduce (Show (m (Thread m r)))
arising from a use of ‘show’
from the context (Show r)
bound by the instance declaration at …
In the second argument of ‘(++)’, namely ‘show m’
In the expression: "Atomic " ++ show m
In an equation for ‘show’: show (Atomic m) = "Atomic " ++ show m
これは、あなたがshow
を呼び出すためにしようとしていると述べていますタイプm (Thread m r)
の値に設定しますが、コンテキストにその制約はありません。だから、それを追加することができます。
instance (Show (m (Thread m r)), Show r) => Show (Thread m r) where
---------------------
GHCがそれを許可する拡張子を示唆して開始しますので、これは、「標準」はHaskellではありません。
Non type-variable argument in the constraint: Show (m a)
(Use FlexibleContexts to permit this)
In the context: (Show (m a), Show r)
While checking an instance declaration
In the instance declaration for ‘Show (Thread m r)’
はのがで、ghci … -XFlexibleContexts
とコマンドライン上(-XFlexibleContexts
を追加してみましょう:set -XFlexibleContexts
のセッション、または{-# LANGUAGE FlexibleContexts #-}
のソースファイル)を使用しています。これは実際にはかなり良い拡張です。今、私たちは別のエラーを取得:
Variable ‘a’ occurs more often than in the instance head
in the constraint: Show (m a)
(Use UndecidableInstances to permit this)
In the instance declaration for ‘Show (Thread m r)’
私たちは、-allこの手段-XUndecidableInstances
を追加することができますが、GHCは証明できないタイプレベルの計算が停止します書いているということです。場合によってはこれは望ましくありませんが、この場合はインスタンスの解決が受け入れ可能なShow
インスタンスを見つけるか、失敗することがわかっています。今、コンパイラはそれを受け入れ、そして我々はShow
インスタンスを試すことができ、m ~ []
とr ~ Int
のような単純な何かを言う:
> Atomic [Atomic [Return 1, Return 2]] :: Thread [] Int
Atomic [Atomic [Return 1,Return 2]]
しかし、あなたは「doesnの型コンストラクタにm
を設定すると、これは動作しませんのでご注意しますtは任意のShow
インスタンスは、そのようなIO
などがあります。また
> Atomic (return (Atomic (return (Return 1) >> return (Return 2)))) :: Thread IO Int
No instance for (Show (IO (Thread IO Int)))
arising from a use of ‘print’
In a stmt of an interactive GHCi command: print it
を、また、あなたはShow
インスタンスの結果にいくつかの括弧を逃していることに気付くことがあります。
> Atomic (Right (Atomic (Left "asdf"))) :: Thread (Either String) Int
Atomic Right Atomic Left "asdf"
これは私があなたに残す簡単な修正です。
これはFree
の方法により、記事からのデータ型などToy
で動作するようにあなたのインスタンスを有効にする必要があります。
> Atomic (Free (Output "foo" (Pure (Return "bar"))))
Atomic (Free (Output "foo" (Pure Return ("bar"))))
は、 'M'は 'IO'または' Maybe'のような* *型のコンストラクタです。完全な型( 'IO()'や 'Maybe String'など)ではありません。しかし 'm(Thread m r)'は完全な型です。 – immibis
さらに、データ・コンストラクタ 'Atomic'は2つではなく1つの引数をとります。 – immibis