2016-09-25 81 views
2

我想了解從哈斯克爾recursion-schemes包這個非常抽象的遞歸函數是如何工作的(或者更確切地說,它做什麼!) - 從this filegpostpro如何「逃離monad」?

class Functor (Base t) => Corecursive t where 

    [...] 

    -- | A generalized postpromorphism 
    gpostpro 
    :: (Recursive t, Monad m) 
    => (forall b. m (Base t b) -> Base t (m b)) -- distributive law 
    -> (forall c. Base t c -> Base t c)   -- natural transformation 
    -> (a -> Base t (m a))      -- a (Base t)-m-coalgebra 
    -> a          -- seed 
    -> t 
    gpostpro k e g = a . return where a = embed . fmap (ana (e . project) . a . join) . k . liftM g 

特別,我想了解的是:它是如何應用g函數提到單子類型的構造函數m,但然後返回t類型的值,它沒有提及或取決於m?我認爲從任意monads逃脫是不可能的在Haskell!

我首先將源文件加載到Intero中,嘗試使用它的類型點功能,但是嘗試failed

然後,我使用cabal repl將它加載到GHCi中,並試圖通過組合函數來逐個跟蹤類型,使用GHCi幫助進行類型推斷,方法是註釋定義的各個位。但是,當我到達fmap時,我無法確定要評論的內容,因爲如果我沒有註釋遞歸調用a,但註釋掉了其他內容,我認爲它可能不會編譯,因爲部分註釋掉了定義a將不具有正確的類型。

+1

您可以放置​​'_代替任何表達式來詢問GHC的類型。 – arrowd

+0

和wrt。轉義:'t'屬於'遞歸'類,這意味着它具有'* - > *'種類。這暗示了gpospro返回類型不是逃避任何事情,而是被包含進某些東西。這可能是一個monad。 – arrowd

+1

@arrowd如果是這種情況,上面的類型簽名將是不可能的,因爲您不能擁有類型爲'* - > *'的返回類型。 –

回答

2

我設法讓ghci告訴我在( ...... :: _)的周圍是什麼類型的子表達式。

原來,訣竅是,在「分配律」 k讓你推臨時Base類型裏面的單子,然後embed方法允許你用臨時Base類型分配並取回t。例如,如果確實具體類型t沒有提及IO,那麼例如爲IO monad編寫這樣的(安全地)k將是不可能的。所以這裏沒有什麼魔法 - 也就是說沒有辦法使用這個函數從monad中逃脫,否則這些monad就會像IO一樣無法逃脫。

+0

然後,將您自己的答案標記爲答案。 – arrowd