2016-09-29 15 views
3

これは私を困惑させます。どのようにFunctorのインスタンスを書くかnewtype Mu f = InF {outF :: f (Mu f)}Functorインスタンスfor(newtype Mu f = InF {outF :: f(Mu f)})

+3

newtype Mu f a = InF {outF :: f(Mu f a)} 'を実行すると、'インスタンスFunctor f => Functor(Mu f) 'が可能です。これは 'Pure'コンストラクタなしでは' Free'です。 – user2297560

+0

この問題を回避するにはhttps://github.com/ekmett/recursion-schemes/pull/23をチェックしてください。 – phadej

+0

興味深いことに、これは第16章からの練習です。第1原則からの* HaskellプログラミングのFunctor *。 –

答えて

7

できません。 cのインスタンスFunctor cを定義するには、c* -> *である必要があります。だからあなたのケースでは、Muはその種のものだったはずです。つまり、その引数f*であったはずです。しかし、これは明らかではありません。fを別のもの(Mu f)に適用しているためです。 Muがファンクタた場合

もっと簡単に言えば、あなたはどんなf用タイプMu fの値にfmapを使用することができます。しかし、これにより、タイプパラメータを他のタイプに変更することができました。例えば、の値をMu fに適用すると、Mu Intの値を返す必要があります。しかし、その値のoutFには意味をなさないタイプInt (Mu Int)があったので、そのような値を形成することはできません。

+0

'Functor'(' * - > * ')で必要とされていないことを強調するために、明示的な種類の署名' Mu ::(* - > *) - > * 'を追加します。親切なエラーを取得します。 – chi

4

rednebはMuは、通常のFunctorすることができない理由の良い説明を与えるが、私はそれが可能だろうか役に立つかわからないけど、あなたは

{-# LANGUAGE RankNTypes #-} 

newtype Mu f = InF {outF :: f (Mu f)} 

mumap :: Functor f => (forall a. f a -> g a) -> Mu f -> Mu g 
mumap f (InF m) = InF $ f $ fmap (mumap f) m 

としてMuためファンクタのようなマッピング操作の並べ替えを実装することができますあなたの場合。 :)

+1

IOW 'Mu'は、タイプコンストラクタ' * - > * '(その変形は' for x x '' f x - > g x''の自然な変換です)のカテゴリからのファンクタで、Haskell型 '' 'と関数 –

0

Muのわずかな再フレージング、user2297560年代は異なる、ムーのためのFunctorのインスタンスを認めるのに十分である:

-- Natural transformations 
type g ~> h = forall a. g a -> h a 

class HFunctor f where 
    ffmap :: Functor g => (a -> b) -> f g a -> f g b 
    hfmap :: (Functor g, Functor h) => (g ~> h) -> (f g ~> f h) 

newtype Mu f a = In { unIn :: f (Mu f) a } 

instance HFunctor f => Functor (Mu f) where 
    fmap f (In r) = In (ffmap f r) 

この製剤は、パトリシア・ニールの紙Haskell Programming with Nested Types: A Principled Approachから来ています。