シグネチャ:: (Monad m) => m a -> a
の組み込み関数はありますか?
Hoogleはそのような機能はないと言っています。
理由を説明できますか?
モナドは2つの関数のみを提供します:
return :: Monad m => a -> m a
(>>=) :: Monad m => m a -> (a -> m b) -> m b
これらはどちらもm a
型の値を返すため、これらを組み合わせてMonad m => m a -> a
型の関数を取得する方法はありません。そのためには、これらの2つの関数以外にも必要なものがあり、モナドであるということよりもm
について詳しく知る必要があります。
たとえば、Identity
モナドにはrunIdentity :: Identity a -> a
があり、いくつかのモナドには同様の機能がありますが、一般的に提供する方法はありません。実際、モナドから「エスケープ」できないことは、IO
のようなモナドにとって不可欠です。
おそらくこれよりも良い答えがありますが、型(Monad m) => m a -> a
を使用できない理由を確認する1つの方法は、nullモナドを検討することです。
data Null a = Null
instance Monad Null where
return a = Null
ma >>= f = Null
(Monad m) => m a -> a
はNull a -> a
を意味します。つまり、何もないところから何かを取得します。それはできません。
Monad
は分解用のパターンではなく、合成用のパターンであるため、これは存在しません。それが定義するインターフェースと一緒に、いつでもより多くのピースを置くことができます。何かを分解することについては何も言っていません。
何かを取り出すことができない理由を尋ねるのは、JavaのIterator
インターフェースに、反復する対象に要素を追加するメソッドが含まれていない理由を尋ねるのと同じです。 Iterator
インターフェースの目的ではありません。
そして、一種の抽出関数を持つ特定の型についてのあなたの引数は、まったく同じ方法に従います。 Iterator
の特定の実装には、add
関数がある場合があります。しかし、それがIterator
sの目的ではないため、特定のインスタンスでのそのメソッドの存在は関係ありません。
そして、fromJust
の存在も同様に無関係です。これは、Monad
が説明する動作の一部ではありません。他の人は、extract
で作業する価値のない型の例をたくさん挙げています。しかし、これらの型は、Monad
の意図されたセマンティクスを引き続きサポートしています。これは重要。これは、Monad
が、あなたが認めているよりも一般的なインターフェースであることを意味します。
そのような関数があったとしましょう:
extract :: Monad m => m a -> a
これで、次のような「関数」を書くことができます。
appendLine :: String -> String
appendLine str = str ++ extract getLine
extract
関数が終了しないことが保証されていない限り、appendLine "foo"
の結果は(a)"foo"
以外のものに依存するため、これは参照透過性に違反します。異なるコンテキストで評価した場合の異なる値。
あるいは、もっと簡単に言えば、実際に役立つextract
操作があった場合、Haskellは純粋に機能しません。
シグネチャ
:: (Monad m) => m a -> a
の組み込み関数はありますか?
Hoogleが存在しないと言った場合は、おそらく存在しません。「組み込み」の定義が「ベースライブラリ内」であると想定します。
Hoogleはそのような機能はないと言っています。理由を説明できますか?
Hoogleがそのタイプシグネチャに一致する関数をベースライブラリで見つけられなかったので、それは簡単です!
もっと真剣に、私はあなたがモナドの説明を求めていたと思います。問題は安全性と意味です。 (また参照してください magicMonadUnwrap :: Monad m => m a -> a
)に関する以前の私の考え )
タイプ[Int]
の値があると言ったとしましょう。 []
がモナドであることはわかっているので、これはMonad m => m Int
型の値があることを伝えるのと似ています。それでは、Int
を[Int]
から取得したいとします。さて、どのInt
が欲しいですか?最初の1つ?最後の?私があなたに言った値が実際に空のリストである場合はどうなりますか?その場合、あなたに与えるInt
さえありません!したがって、リストの場合、単一の値を試して抽出するのはunsafeです。安全(空ではないリスト)の場合でも、リスト固有の関数(たとえば、head
)を使用して、自分の意味を明確にする必要がありますf :: [Int] -> Int
を希望する。うまくいけば、ここからMonad m => m a -> a
の意味が十分に定義されていないことを直感的に理解できます。同じモナドに対して複数の意味を持つこともあれば、一部のモナドに対してまったく何も意味しないこともあり、場合によっては単に安全ではないこともあります。
それは意味をなさないかもしれないからです(実際にはdoesは多くの場合意味を成しません)。
たとえば、次のようにパーサーモナドを定義します。
data Parser a = Parser (String ->[(a, String)])
現在、Parser String
からString
を取得する適切なデフォルトの方法はまったくありません。実際、モナドだけで文字列を取り出す方法はまったくありません。
http://hackage.haskell.org/package/comonad-5.0.4/docs/Control-Comonad.html には、便利なextract
関数と、これに関連する他のいくつかの関数があります。 =
これは一部のファンクタ/モナドに対してのみ定義されており、必ずしも全体の答えを与えるわけではなく、anの答えを与えます。したがって、comonadのサブクラスが存在する可能性があり、制御を行うことができる答えを選択する中間段階を提供します。おそらくTraversableの可能なサブクラスに関連しています。そのようなことがどこで定義されているのかわかりません。
Hoogleがこの関数をまったくリストしない理由は、comonadパッケージがインデックス付けされていないためであると思われます。そうでない場合、モナド制約が警告され、extract
がComonad
インスタンス。おそらくこれは、フーグルパーサーが不完全であり、一部のコード行で失敗するためです。
私の代わりの答え:
monad >>= \a -> return $ your code uses a here
を使用し、出力を出力する方法でモナドを "IO()"に変換できる限り、完了しました。これは抽出のようには見えませんが、数学は現実の世界とは異なります。まあ、技術的には、IOモナド用の nsafePerformIO があります。
しかし、名前自体が示すように、この関数は悪であり、あなたが本当に何をしているのかを知っている場合(そして、あなたが知っているかどうかを尋ねてください、それからあなたはしません)