簡體   English   中英

不使用 monadic bind 使用循環寫下 mfix 的情況

[英]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.

所以,這是我的問題:

  1. 是否有任何其他示例可以表明mfix''不完全是mfix
  2. Maybe'這樣嚴格綁定的 monad 在實踐中是否有趣?
  3. 是否有任何示例表明mfix'不完全是我沒有找到的mfix

關於IO的一個小旁注:

mfix3 k' = 
    let 
       k = return . k'
       f ~(_, d) = fmap ((,) d) (d >>= k)
    in (join . flip runKleisli () . loop . Kleisli) f

不要擔心所有的returnjoin ——它們在這里只是為了讓mfix3mfix的類型匹配。 這個想法是我們傳遞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,它實際上並沒有為MapIntMap定義Monad實例,並且SeqMonad實例在序列的元素中是惰性的)。

另請注意,尚不清楚單子定律是否考慮了嚴格性。 如果你這樣做了,那么這些東西就不是合法的單子,因為它們違反了左恆等律: (return x >>= k) = kx for x = undefined

是否有任何示例表明mfix'不完全是我沒有找到的mfix

如果您在標准庫中使用mfix來定義loop ,那么我認為mfix' = mfix ,盡管我無法完成證明(我可能錯過了一個好技巧,或者缺少 MonadFix 法則)。

正如評論中所暗示的那樣,主要爭論點是嚴格性。 您對mfix'的定義和標准庫對loop的定義都小心地將參數 function 擴展為更惰性(分別使用惰性模式( ~(_, d) )和snd ;這兩種技術是等效的)。 如果恰好放棄其中一項預防措施,則mfixmfix'仍然相等。 如果兩者都被刪除,則存在不匹配( mfix /= mfix' )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM