2

このタイプの fmap を書き込もうとしています

data Triangle a  = Triangle {t0 :: Point a, t1 ::  Point a, t2 ::  Point a}

ここで、ポイントは次のように定義されます

data Point a = Point {px :: a, py :: a, pz :: a}

そして、私のインスタンス定義は

instance Functor Triangle where 
    fmap f (Triangle v0 v1 v2) = Triangle (f v0) (f v1) (f v2)

次のコンパイル エラーが発生し、その理由がわかりません

C:\Scripts\Haskell\Geometry.hs:88:1:
     チェックが発生します: 無限型を構築できません: a = Point a
     fmap の型を一般化する場合
     Functor Triangle のインスタンス宣言内

何か案は?

4

3 に答える 3

8
instance Functor Point where
    fmap f (Point v0 v1 v2) = Point (f v0) (f v1) (f v2)

instance Functor Triangle where
    fmap f (Triangle v0 v1 v2) = Triangle (fmap f v0) (fmap f v1) (fmap f v2)

Triangle インスタンスでは、fですa -> bPoint a -> Point b最初に変換する必要があります。次に、にfmap f変換Triangle aできTriangle bます。f(私があなたの意図を正しく理解していれば、9 つのオブジェクトに適用していることに注意してください) [編集: 27 歳でした]

于 2009-12-15T22:42:16.873 に答える
8

前の回答で正しい解決策が得られますが、ここで何が起こっているのかをより明確にすることが役立つ場合があります。のタイプfmap

fmap :: Functor f => (a -> b) -> f a -> f b

したがって、宣言の型推論はinstance次のように進みます。

  1. ではfmap f (Triangle v0 v1 v2)f何らかのタイプが必要a -> bであり、タイプ(Triangle v0 v1 v2)が必要Triangle aです。
    • の定義によりTrianglev0v1、およびv2はタイプ を持つ必要がありますPoint a
    • は、、およびにf適用されるため、その引数の型は でなければなりません。v0v1v2aPoint a
    • おっと、a = Point a満足できません。

定義が機能するのはなぜTriangle (fmap f v0) (fmap f v1) (fmap f v2)ですか?:

  1. ではfmap f (Triangle v0 v1 v2)f何らかのタイプが必要a -> bであり、タイプ(Triangle v0 v1 v2)が必要Triangle aです。
    • の定義によりTrianglev0v1、およびv2はタイプ を持つ必要がありますPoint a
    • 上記のようにPointが のインスタンスであると仮定すると、は の結果の型であるタイプを持っている必要があります。と についても同様です。Functorfmap f v0Point bbfv1v2
    • したがってTriangle (fmap f v0) (fmap f v1) (fmap f v2)、 type がありTriangle bます。
    • QED。
于 2009-12-16T03:22:46.597 に答える
2

ところで、の興味深い特性は、ファンクターの法則Functorを満たす可能性のあるインスタンスが1つしかないことです。

さらに良いことに、このインスタンスは、派生パッケージを使用して自動的に生成できます。

{-# LANGUAGE TemplateHaskell #-}

import Data.DeriveTH (derive, makeFunctor)

data Point a = Point {px :: a, py :: a, pz :: a}
$(derive makeFunctor ''Point)

data Triangle a  = Triangle {t0 :: Point a, t1 ::  Point a, t2 ::  Point a}
$(derive makeFunctor ''Triangle)

の定義を変更することにした場合Triangle、そのFunctorインスタンスが自動的に維持されるため、これは部分的に勝利です。

于 2009-12-17T11:16:01.573 に答える