[英]What is the difference between Fix, Mu and Nu in Ed Kmett's recursion scheme package
在Ed Kmett的recursion-scheme
包中,有三個聲明:
newtype Fix f = Fix (f (Fix f))
newtype Mu f = Mu (forall a. (f a -> a) -> a)
data Nu f where
Nu :: (a -> f a) -> a -> Nu f
這三種數據類型有什么區別?
Mu
表示遞歸類型作為其折疊, Nu
表示它作為其展開。 在Haskell中,這些是同構的,並且是表示相同類型的不同方式。 如果你假裝Haskell沒有任意遞歸,這些類型之間的區別變得更有趣: Mu f
是最少的(最初的)固定點f
和Nu f
是其最大的(終端)的固定點。
f
的固定點是T
和f T
之間的類型T
同構,即in :: f T -> T
, out :: T -> f T
的一對反函數。 類型Fix
只使用Haskell的內置類型遞歸來直接聲明同構。 但是你可以實現Mu
和Nu
輸入/輸出。
舉一個具體的例子,假裝你不能寫遞歸值。 Mu Maybe
的居民Mu Maybe
,即值:: forall r. (Maybe r -> r) -> r
:: forall r. (Maybe r -> r) -> r
,是自然的,{0,1,2,...}; Nu Maybe
的居民,即值:: exists x. (x, x -> Maybe x)
:: exists x. (x, x -> Maybe x)
,是conaturals {0,1,2,...,∞}。 想想這些類型的可能價值,看看為什么Nu Maybe
有一個額外的居民。
如果你想對這些類型有一些直覺,那么在沒有遞歸的情況下實現以下內容可能是一種有趣的練習(大致按難度遞增順序):
zeroMu :: Mu Maybe
, succMu :: Mu Maybe -> Mu Maybe
zeroNu :: Nu Maybe
, succNu :: Nu Maybe -> Nu Maybe
, inftyNu :: Nu Maybe
muTofix :: Mu f -> Fix f
, fixToNu :: Fix f -> Nu f
inMu :: f (Mu f) -> Mu f
, outMu :: Mu f -> f (Mu f)
inNu :: f (Nu f) -> Nu f
, outNu :: Nu f -> f (Nu f)
您也可以嘗試實現這些,但它們需要遞歸:
nuToFix :: Nu f -> Fix f
, fixToMu :: Fix f -> Mu f
Mu f
是最不固定的點, Nu f
是最大的,所以寫一個函數:: Mu f -> Nu f
很容易,但寫一個函數:: Nu f -> Mu f
很難; 就像在逆流而行。
(有一點,我的意思是寫出這些類型的更詳細的解釋,但這種格式可能有點太長了。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.