2016-01-03 73 views
5

一種方式是說,這是在endofunctors類別的初始獨異,其對象是endofunctors從CC(某些類別C的),箭頭是它們之間的自然轉換。如果我們把CHask,該endofunctor被所謂Functor在Haskell,這是從* -> *函子,其中*代表Hask免費單子和自由運作來形容免費單子

通過initiality的對象,從endofunctor t任何映射到一個獨異mEnd(Hask)誘導從Free tm的地圖。

說,否則,從一個仿函數t任何改造自然的單子m誘導從Free tm

自然改造我本來期望能夠寫一個函數

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:該代碼啓用

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

回答

7

Haskell的翻譯似乎是錯誤的。一個很大的暗示是你的free實現不會在任何地方使用monadic綁定(或連接)。你可以找到free作爲foldFree如下定義:

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專門到t (Free t a) -> m (Free t a),從而消除一個Free層一舉。

+0

當然......這的確很明顯 – nicolas

3

我不知道類別理論的一部分,但Haskell部分絕對不是你的原始實現和原始類型簽名很好的類型。

鑑於

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

當你在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 

並由此

free f :: forall a. Free t a -> m a 

導致

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

這樣一來就能到t (m a)摺疊成你想要的m a,你需要在它應用f(以「轉tm」),然後利用以下事實: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

,它是使用連接而不是綁定的其他答案的不錯選擇。我希望我能標誌着這兩個答案爲正確 – nicolas

+1

注意,這'free'是爲'Free'遞歸原理方面:'免費F =倍(加入F。)return'其中'倍::仿函數F => (fb→b)→a→b→自由fa→b'。相比較而言,庫['foldFree'](https://hackage.haskell.org/package/free-4.12/docs/src/Control-Monad-Free.html#foldFree)用'>> ='不需要'Functor'約束,因爲在Haskell的'Free'數據類型適用於所有'˚F:: * - > *'參數,我們可以直接計算在該結構(儘管'免費fa'與非函子' f'不是很有用)。 –