![](/img/trans.png)
[英]Could liftM be too strict for a Functor instance, if we are writing down mfix with it?
[英]Cases in which we shall not use monadic bind to write mfix down using loop
我一直在嘗試使用Control.Arrow.loop
寫下mfix
。 我想出了不同的定義,並想看看哪個是mfix
的實際工作相似。
因此,我認為正確的解決方案如下:
mfix' :: MonadFix m => (a -> m a) -> m a
mfix' k = let f ~(_, d) = sequenceA (d, k d)
in (flip runKleisli () . loop . Kleisli) f
可以看到, loop. Kleisli
loop. Kleisli
的論點適用於Applicative
實例。 我發現這是一個好兆頭,因為我們的打結大多被(>>=)
在正確論點中的嚴格性所破壞。
這是另一個 function。 我可以說這不是mfix
的全部工作方式,但我發現的唯一情況不是很自然。 看一看:
mfix'' k = let f ~(_, d) = fmap ((,) d) (return d >>= k)
in (flip runKleisli () . loop . Kleisli) f
據我了解,並非所有嚴格的右手綁定都完全強制其論點。 例如,在IO
的情況下:
GHCi> mfix'' ((return :: a -> IO a) . (1:))
[1,1,1,1,1,Interrupted.
所以,我決定解決這個問題。 我剛剛接受了Maybe
並在Just x >>= k
中強制x
:
data Maybe' a = Just' a | Nothing' deriving Show
instance Functor Maybe' where
fmap = liftM
instance Applicative Maybe' where
pure = return
(<*>) = ap
instance Monad Maybe' where
return = Just'
Nothing' >>= k = Nothing'
Just' x >>= k = x `seq` k x
instance MonadFix Maybe' where
mfix f = let a = f (unJust' a) in a
where unJust' (Just' x) = x
unJust' Nothing' = errorWithoutStackTrace "mfix Maybe': Nothing'."
我們手上有這個:
GHCi> mfix ((return :: a -> Maybe' a) . (1:))
[1,1,1,1,1,Interrupted.
GHCi> mfix' ((return :: a -> Maybe' a) . (1:))
[1,1,1,1,1,Interrupted.
GHCi> mfix'' ((return :: a -> Maybe' a) . (1:))
Interrupted.
所以,這是我的問題:
mfix''
不完全是mfix
?Maybe'
這樣嚴格綁定的 monad 在實踐中是否有趣?mfix'
不完全是我沒有找到的mfix
? 關於IO
的一個小旁注:
mfix3 k' =
let
k = return . k'
f ~(_, d) = fmap ((,) d) (d >>= k)
in (join . flip runKleisli () . loop . Kleisli) f
不要擔心所有的return
和join
——它們在這里只是為了讓mfix3
和mfix
的類型匹配。 這個想法是我們傳遞d
本身而不是將return d
到右側的(>>=)
。 它為我們提供了以下信息:
GHCi> mfix3 ((return :: a -> IO a) . (1:))
Interrupted.
然而,例如(感謝Li-yao Xia的評論) :
GHCi> mfix3 ((return :: a -> e -> a) . (1:)) ()
[1,1,1,1,1,Interrupted.
編輯:感謝HTNW在評論中對模式匹配的重要說明:最好使用\ ~(_, d) ->...
,而不是\ (_, d) ->...
。
這是部分答案,我希望總比沒有答案好。
是否有任何其他示例可以表明 mfix'' 不完全是 mfix?
我們也可以通過使用return
strict 而不是(>>=)
來區分mfix''
和mfix
。
具有如此嚴格綁定的 monad,例如 Maybe',在實踐中是否有趣?
可能不是。 (關於是否存在“實際”例子的問題不容易否定。)
元素嚴格的容器可能就是一個例子。 (如果您想知道官方容器 package,它實際上並沒有為Map
和IntMap
定義Monad
實例,並且Seq
的Monad
實例在序列的元素中是惰性的)。
另請注意,尚不清楚單子定律是否考慮了嚴格性。 如果你這樣做了,那么這些東西就不是合法的單子,因為它們違反了左恆等律: (return x >>= k) = kx
for x = undefined
。
是否有任何示例表明
mfix'
不完全是我沒有找到的mfix
?
如果您在標准庫中使用mfix
來定義loop
,那么我認為mfix' = mfix
,盡管我無法完成證明(我可能錯過了一個好技巧,或者缺少 MonadFix 法則)。
正如評論中所暗示的那樣,主要爭論點是嚴格性。 您對mfix'
的定義和標准庫對loop
的定義都小心地將參數 function 擴展為更惰性(分別使用惰性模式( ~(_, d)
)和snd
;這兩種技術是等效的)。 如果恰好放棄其中一項預防措施,則mfix
和mfix'
仍然相等。 如果兩者都被刪除,則存在不匹配( mfix /= mfix'
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.