6

このコードが正しい理由

instance Functor IO where -- note that IO isn't parametrized, and it's correct
    fmap f action = do
        result <- action
        return (f result)

しかし、次のコードにはコンパイラ エラーがありますか?

class Print a where
    print :: a -> String

data A t = A t
instance Print A where  -- error: expecting one more argument to `A'
    print a = "abc"
4

3 に答える 3

11

これは、種類が一致しないためです。通常の型には kindがありますが、 or*などの型コンストラクターには kindがあり、型を返すために型パラメーターが必要であることを示しています。AIO* -> *

クラスの定義ではPrint、コンパイラは、aがプレーン タイプとして使用されているため、 kind が必要であると推論し*ます。ただし、Functorkind の型コンストラクターでは機能し* -> *ます。

class Functor f where
  fmap :: (a -> b) -> f a -> f b

ここで、fはプレーン タイプとしてではなく、タイプ コンストラクターとして使用されるため、kind is と推測され* -> *ます。:kindこれは、GHCiのコマンドで確認できます。

> :kind Print
Print :: * -> Constraint
> :kind Functor
Functor :: (* -> *) -> Constraint 
于 2012-10-25T21:27:37.683 に答える
9

あなたが言う時

class Print a where
   print' :: a -> String

aあなたはそれがタイプでなければならないことを確認しますが、あなたが言うとき

data A t = A t

A型コンストラクターを作成します-A型ではありませんがA Int、たとえば型です。Aは型に対する一種の関数ですがa、Print クラスの は型関数ではなく型値でなければなりません。

あなたができる

instance Print (A Int) where
  print' a = "abc"

クラスが型コンストラクターを要求するIOため、問題ありません。Functor

class Functor f where
  fmap :: (a -> b) -> f a -> f b

f asinceは型であり、型構築子であり、やare とf同じであることがわかります。あなたはできるでしょうIOA

instance Functor A where  -- OK, A is a constructor, Functor needs one
  fmap f (A x) = A (f x)

そして、あなたはできないでしょう

instance Eq IO where -- not OK - IO is a constructor and Eq needs a type
    (==) = error "this code won't compile"

(標準関数との衝突を避けるためprint'に代わりに使用しました。)printprint

于 2012-10-25T21:13:42.260 に答える
1

クラス定義で指定されたタイプを、インスタンスで使用したタイプで精神的に(またはテキストエディターで)入力してみてください。

から:

class Print a where
    print :: a -> String

data A t = A t

欲しい

instance Print A

したがって、私たちが言ってaいる型クラス定義をインスタンスに置き換えると、次のようになります。A

class Print A where
    print :: A -> String

ええとああ。A -> String関数の型の矢印は左側の型と右側の型を取り、関数の型を示しているため、型としては意味がありません。しかし、 ;で宣言したAので、タイプではありません。は任意の型の型ですが、型コンストラクターです。型に当てはめると型を作ることができますが、それ自体は違うものです。したがって、のインスタンスにすることはできますが、それ自体にすることはできません。Adata A tA ttAAA tPrintA

では、なぜうまくinstance Functor IOいったのでしょうか。クラス定義を見てみましょう。

class Functor f where
    fmap :: (a -> b) -> f a -> f b

では、次のように置き換えIOてみましょう。f

class Functor IO where
    fmap :: (a -> b) -> IO a -> IO b

sはIO最終的に型パラメーターに適用されるため、すべてうまくいきます。Intここで、またはA tのインスタンスのような具体的な型を作成しようとすると、問題が発生しますFunctor

于 2012-10-26T04:29:21.173 に答える