4

モナド列から抜け出すことは可能ですか?

たとえば、シーケンスの途中で計算された条件に基づいて、シーケンスから早く抜け出したい場合。たとえば、「do」表記で値をバインドし、その値に基づいてシーケンスを終了または停止したいとします。「パス」機能のようなものはありますか?

ありがとう。

4

4 に答える 4

2

したがって、あなたが探していると思うのはreturn、命令型言語と同等のものです。

def do_something
  foo
  bar
  return baz if quux
  ...
end

Haskell では、モナド チェーンは 1 つの大きな関数アプリケーションにすぎないため、これは機能しません。見栄えを良くする構文がありますが、次のように書くことができます

bind foo (bind bar (bind baz ...)))

途中で適用を「停止」することはできません。幸いなことに、本当に必要な場合は、Contモナドからの回答があります。callCC. これは「call with current continuation」の略で、戻り値の表記を一般化したものです。あなたがSchemeを知っているなら、これはよく知られているはずです。

import Control.Monad.Cont

foo = callCC $ \escape -> do
   foo
   bar
   when baz $ quux >>= escape
   ...

Control.Monad.Cont のドキュメントから恥知らずに盗んだ実行可能な例

whatsYourName name =
  (`runCont` id) $ do
    response <- callCC $ \exit -> do
      validateName name exit
      return $ "Welcome, " ++ name ++ "!"
    return response

validateName name exit = do
  when (null name) (exit "You forgot to tell me your name!")

そしてもちろん、これをIOなどに重ねることができるContトランスフォーマーContT(これは絶対に気が狂います)があります。

補足として、callCCは昔ながらの機能であり、まったく魔法のようなものではないため、実装は大きな課題です

于 2013-07-16T13:36:17.870 に答える
1

だから、私が最初に想像した方法でそれを行う方法はないと思います。これは、命令型ループのブレーク関数に相当します。

しかし、Ingoの回答に基づいて、以下でも同じ効果が得られます。これは非常に簡単です(愚かな私)

doStuff x = if x > 5
            then do
                 t <- getTingFromOutside
                 doHeavyHalculations t
             else return ()

上記の例で「t」をテストする必要がある場合、それがどのように機能するかはわかりません...つまり、バインドされた値をテストし、そこからif決定を行う必要がある場合。

于 2013-07-16T15:24:08.470 に答える
0

定義上、「モナドシーケンス」から抜け出すことはできません。「モナドシーケンス」は、他の値/関数に適用される1つの関数に他ならないことに注意してください。「モナド列」から命令型プログラムができると錯覚したとしても、これは (Haskell では) 正しくありません!

あなたができる唯一のことは、することですreturn ()。この実用的な問題の解決策は、ここで既に名前が付けられています。しかし覚えておいてください: それはモナドから抜け出すことができるという錯覚を与えるだけです!

于 2013-07-16T14:39:23.030 に答える