2017-09-20 2 views
1

関数合成の簡単な定義は次のとおりです。機能組成物は

newtype Compose f g a = 
    Compose { getCompose :: f (g a) } 
    deriving (Eq, Show) 

    instance (Functor f, Functor g) => Functor (Compose f g) where 
    fmap f (Compose fga) = Compose $ (fmap . fmap) f fga 

は、その後、私はせずにfmapを書いてみる:今、私は次の例ている

f (g x) 

または

(f . g) $ x 

組成演算子:

instance (Functor f, Functor g) => Functor (Compose f g) where 
    fmap f (Compose fga) = Compose $ fmap f (fmap f fga) 

とコンパイラが文句:

* Couldn't match type `b' with `g b' 
    `b' is a rigid type variable bound by 
    the type signature for: 
     fmap :: forall a b. (a -> b) -> Compose f g a -> Compose f g b 
    at D:\haskell\chapter25\src\Twinplicative.hs:11:5 
    Expected type: f (g b) 
    Actual type: f b 
* In the second argument of `($)', namely `fmap f (fmap f fga)' 
    In the expression: Compose $ fmap f (fmap f fga) 
    In an equation for `fmap': 
     fmap f (Compose fga) = Compose $ fmap f (fmap f fga) 
* Relevant bindings include 
    fga :: f (g a) 
     (bound at D:\haskell\chapter25\src\Twinplicative.hs:11:21) 
    f :: a -> b 
     (bound at D:\haskell\chapter25\src\Twinplicative.hs:11:10) 
    fmap :: (a -> b) -> Compose f g a -> Compose f g b 
     (bound at D:\haskell\chapter25\src\Twinplicative.hs:11:5) 

組成オペレータなし上記fmapを構成する方法?

+1

'FMAP F(FGAを作曲)=作曲$ FMAP(FMAP F)fga' –

+0

を:fgaに方程式の両辺を適用すると、我々が得ます。私はあなたが持っていれば、それを正しく適用できたと思う。 – dfeuer

答えて

2

fmapの左端のアプリケーションに提供する機能は、タイプa -> bfを入力しているときにタイプg a -> g bである必要があります。 a -> bg a -> g bに、fmap、つまりfmap fを使用してリフトすることができます。私はあなたがゼロからComposeのために自分自身をFunctorインスタンスを実装する方法明記リーの答えを、好き

instance (Functor f, Functor g) => Functor (Compose f g) where 
    fmap f (Compose fga) = Compose $ fmap (fmap f) fga 
1

:外fmapへの第二引数は、fgaのタイプであるタイプf (g a)を持つ必要があります。しかし、私はまた、密接に関連した質問に答える価値があると考えました。つまり、既存のインスタンスから始め、機械的にそれを書き換えて(.)の機能構成を避けますか?したがって、私はこの答えにその質問に取り組んでいます。

(f . g) x = f (g x)は定義式が(.)なので、我々は(fmap . fmap) f = fmap (fmap f)と結論づけます。あなたが実際に機能組成物の定義を与えていない

(fmap . fmap) f fga = fmap (fmap f) fga 
関連する問題