2016-01-03 6 views
5

一つの方法は、それがオブジェクトCからCにendofunctorsている(一部のカテゴリCの)endofunctorsのカテゴリに初期モノイドであると言うことです、矢印がありますそれらの間の自然な変換。私たちはHaskするCを取る場合は、endofunctorは*がinitialityことでHask無料モナドと自由操作

End(Hask)誘導におけるモノイドmへendofunctor tから任意のマップのオブジェクトを表し* -> *からファンクタである、HaskellでFunctorと呼ばれるものですFree tからmまでの地図。

。前記は、さもなければ、モナドmへのFunctor tから任意の自然変換はIを関数を作成することができると予想しているであろうm

からFree tから自然形質転換を誘導

free :: (Functor t, Monad m) => (∀ a. t a → m a) → (∀ a. Free t a → m a) 
free f (Pure a) = return a 
free f (Free (tfta :: t (Free t a))) = 
    f (fmap (free f) tfta) 

これ統一されていないのに対し、以下の作品は

free :: (Functor t, Monad m) => (t (m a) → m a) → (Free t a → m a) 
free f (Pure a) = return a 
free f (Free (tfta :: t (Free t a))) = 
    f (fmap (free f) tfta) 

または署名付きの一般化

free :: (Functor t, Monad m) => (∀ a. t a → a) → (∀ a. Free t a → m a) 

私はカテゴリ理論、またはHaskellへの翻訳で間違いを犯しましたか?

私はここにいくつかの知恵を聞いて興味があると思います。..

PS:それを持つコードはHaskellの翻訳が間違っているようだ

{-# LANGUAGE RankNTypes, UnicodeSyntax #-} 
import Control.Monad.Free 

答えて

7

を可能にしました。大きなヒントは、freeの実装では、モナドのバインド(または結合)をどこでも使用しないことです。あなたは次のように定義してfoldFreeとしてfreeを見つけることができます。

free :: Monad m => (forall x. t x -> m x) -> (forall a. Free t a -> m a) 
free f (Pure a) = return a 
free f (Free fs) = f fs >>= free f 

キーポイントはfは、このように一挙に1 Free層を排除し、t (Free t a) -> m (Free t a)に特化したということです。

+0

もちろん、それは確かに – nicolas

3

私はカテゴリの理論の部分についてはわかりませんが、Haskellの部分は、元の実装と元の型の署名で間違いなくタイプが正しくありません。あなたFree tfta上のパターンマッチ、あなたは

tfta :: t (Free t a) 
f :: forall a. t a -> m a 
free :: (forall a. t a -> m a) -> forall a. Free t a -> m a 

そしてこうして

fmap (free f) :: forall a. t (Free t a) -> t (m a) 
につながる
free f :: forall a. Free t a -> m a 

を得るとき

free :: (Functor t, Monad m) => (∀ a. t a → m a) → (∀ a. Free t a → m a) 

を考えると

だからあなたm a希望にそのt (m a)を折りたたむことができるようにするには、(「mtを回す」に)それにfを適用する必要があり、その後mがモナドであるという事実は、エクスプロイト:

f . fmap (free f) :: forall a. t (Free t a) -> m (m a) 
join . f . fmap (free f) :: forall a. t (Free t a) -> m a 
あなたが freeの第二のブランチを変更することによって、あなたの元の定義を修正することができることを意味し

{-# LANGUAGE RankNTypes, UnicodeSyntax #-} 

import Control.Monad.Free 
import Control.Monad 

free :: (Functor t, Monad m) => (∀ a. t a → m a) → (∀ a. Free t a → m a) 
free f (Pure a) = return a 
free f (Free tfta) = join . f . fmap (free f) $ tfta 

このtypechecks、おそらく多分あなたは:)を望むものかもしれませんさ

+1

です。これは、bindの代わりにjoinを使用して、他の答えに代わる素晴らしい方法です。私はこれら2つの答えを正しいものとしてマークしたいと思います。 – nicolas

+1

この 'free'は' Free'の再帰の原則の点でです: 'free f = fold(join.f)return' 'fold :: Functor f => (fb-> b) - >(a-> b) - >フリーfa-> b'である。これと比較して、 '' foldFree'(https://hackage.haskell.org/package/free-4.12/docs/src/Control-Monad-Free.html#foldFree)の '' = ''は、 Haskellの 'Free'データ型はすべての' f :: * - > * 'パラメータに対して有効で、その構造体を直接計算することができます(' Fun fa'は非ファンクタ ' fはあまり有用ではない)。 –