47

署名付きの組み込み関数はあります:: (Monad m) => m a -> aか?

Hoogleは、そのような機能はないと言っています。

理由を説明できますか?

4

8 に答える 8

53

モナドは次の 2 つの関数のみを提供します。

return :: Monad m => a -> m a
(>>=) :: Monad m => m a -> (a -> m b) -> m b

これらは両方とも type の何かを返すm aため、これらを何らかの方法で組み合わせて type の関数を取得する方法はありませんMonad m => m a -> amそのためには、これら 2 つの関数以外の関数が必要になるため、それがモナドであるということ以上のことを知る必要があります。

たとえば、Identityモナドには がrunIdentity :: Identity a -> aあり、いくつかのモナドには同様の機能がありますが、それを一般的に提供する方法はありません。実際、モナドから「脱出」できないことは、 のようなモナドにとって不可欠ですIO

于 2011-12-19T21:31:46.157 に答える
26

おそらくこれよりも良い答えがありますが、型を持てない理由を確認する 1 つの方法は(Monad m) => m a -> a、null モナドを検討することです。

data Null a = Null

instance Monad Null where
    return a = Null
    ma >>= f = Null

Now(Monad m) => m a -> aは を意味しますNull a -> a。つまり、何もないところから何かを得るということです。そんなことはできません。

于 2011-12-19T21:29:06.287 に答える
18

これはMonad、分解のパターンではなく合成のパターンであるため、存在しません。それが定義するインターフェースを使用して、いつでもより多くのピースを組み合わせることができます。何かを分解することについては何も言いません。

何かを取り出すことができない理由を尋ねることは、Java のIteratorインターフェースに、繰り返し対象に要素を追加するためのメソッドが含まれていない理由を尋ねるようなものです。それはIteratorインターフェースの目的ではありません。

そして、ある種の抽出関数を持つ特定のタイプに関するあなたの議論は、まったく同じ方法で続きます。の特定の実装には機能Iteratorがある場合がありaddます。しかし、それはIterators の目的ではないため、特定のインスタンスでのそのメソッドの存在は関係ありません。

の存在もfromJust同様に無関係です。Monadこれは、説明することを意図した動作の一部ではありません。extract他の人は、取り組む価値のない型の例をたくさん挙げています。しかし、これらの型は の意図したセマンティクスを引き続きサポートしMonadます。これは重要。これはMonad、あなたが信用しているよりも一般的なインターフェースであることを意味します。

于 2011-12-19T21:56:30.670 に答える
13

次のような関数があったとします。

extract :: Monad m => m a -> a

これで、次のような「関数」を作成できます。

appendLine :: String -> String
appendLine str = str ++ extract getLine

関数が決して終了しないことが保証されていない限りextract、これは参照透過性に違反します。これは、の結果が(a)appendLine "foo"以外のものに依存し"foo"、(b) 異なるコンテキストで評価されると異なる値に評価されるためです。

もっと簡単に言えば、実際に有用なextract操作があったとしても、Haskell は純粋に機能するわけではありません。

于 2011-12-20T00:19:14.207 に答える
8

署名付きの組み込み関数はあります:: (Monad m) => m a -> aか?

Hoogleが「存在しない」と言った場合、「組み込み」の定義が「ベースライブラリ内」であると仮定すると、おそらく存在しないでしょう。

Hoogleは、そのような機能はないと言っています。理由を説明できますか?

Hoogleは、その型シグネチャに一致する関数をベースライブラリで見つけられなかったため、これは簡単です。

もっと真剣に、あなたは単調な説明を求めていたと思います。問題は安全性意味です。(に関する私の以前の考えmagicMonadUnwrap :: Monad m => m a -> aも参照してください)

タイプが。の値があると言ったとします[Int]。これはモナドであることがわかっているので[]、これは、タイプが。の値があることを通知するのと似ていますMonad m => m IntIntそれで、あなたがそれから抜け出したいとしましょう[Int]。さて、Intあなたはどちらが欲しいですか?最初の1つ?最後は?私があなたに話した値が実際に空のリストである場合はどうなりますか?その場合、Intあなたに与えるものすらありません!したがって、リストの場合、そのように意地悪な単一の値を抽出しようとするのは安全ではありません。安全な場合(空でないリスト)でも、必要に応じて意味head明確にするために、リスト固有の関数(たとえば)が必要です。うまくいけば、あなたはここからその意味を直感することができますf :: [Int] -> IntMonad m => m a -> a単に明確に定義されていません。同じモナドに対して複数の意味を持つ場合もあれば、一部のモナドに対してはまったく意味がない場合もあり、場合によっては、単に安全ではないこともあります。

于 2011-12-19T23:02:06.023 に答える
6

意味がないかもしれないからです (実際には、多くの場合意味がありません)。

たとえば、次のように Parser モナドを定義できます。

data Parser a = Parser (String ->[(a, String)])

String現在、 aからa を取得する賢明なデフォルトの方法はまったくありませんParser String。実際には、Monad だけでこれから文字列を取得する方法はまったくありません。

于 2011-12-19T21:27:35.877 に答える
0

技術的には、IO モナドにはunsafePerformIOがあります。

しかし、名前自体が示すように、この関数は悪であり、自分が何をしているのかを本当に知っている場合にのみ使用する必要があります (知っているかどうかを尋ねなければならない場合は、知っていません)。

于 2011-12-20T20:53:04.863 に答える