2

私はGHCiのhasboltモジュールをいじっていて、いくつかの脱糖に興味がありました。次のようにパイプを作成して、Neo4j データベースに接続しています。

ghci> pipe <- connect $ def {credentials}

そしてそれはうまくいきます。しかし、(<-)演算子の型が何なのか気になります (GHCi は教えてくれません)。ほとんどの脱糖の説明は、

do x <- a
   return x

脱糖する

a >>= (\x -> return x)

しかし、行だけはx <- aどうですか?returnしたくpipe :: Pipeないのでを追加しても役に立ちませんが、 and /を使用して脱糖しようとするとpipe :: Control.Monad.IO.Class.MonadIO m => m Pipe、それなしでは機能しません。(>>=) :: Monad m => m a -> (a -> m b) -> m bbindreturnpure

理想的には、 asComonadを使用できるようにインスタンスを作成するのが最善のように思えますが、私には理解できないので困っています。extract :: Monad m => m a -> apipe = extract $ connect $ def {creds}(<-)

もう1つの奇妙な点は、(<-)haskell関数として扱うと、最初の引数が範囲外の変数であるということですが、それはそれを意味するものではありません

(<-) :: a -> m b -> b

何でも自由変数として使用できるわけではないからです。たとえば、パイプをNum型やBool. 変数は、実際にはString;ではないことを除いて、「文字列」っぽいものでなければなりません。実際ににバインドしようとすることは絶対にできませんString。したがって、通常の意味での haskell 関数ではないように見えます (自由変数の名前空間から値を取得する関数のクラスがない限り... 可能性は低いです)。では、(<-)正確には何ですか?を使用して完全に置き換えることはできますextractか? それは脱糖/回避する最良の方法ですか?

4

3 に答える 3

4

理想的には、extract :: Monad m => ma -> a as pipe = extract $ connect $ def {creds} を使用して有効にするために Comonad インスタンスを作成するのが最善のようですが、理解できないことは私を悩ませます(<-)。

Comonad は Monads とは何の関係もありません。実際、ほとんどのモナドには有効な Comonad インスタンスがありません。[]モナドを考えてみましょう:

instance Monad [a] where
  return x = [x]
  xs >>= f = concat (map f xs)

Comonad インスタンスを作成しようとすると、定義できませんextract :: m a -> a

instance Comonad [a] where
  extract (x:_) = x
  extract [] = ???

これは、モナドについて興味深いことを教えてくれます。つまり、 type で一般的な関数を書くことはできないということMonad m => m a -> aです。言い換えれば、Monad についての追加の知識がなければ、Monad から値を「抽出」することはできません。

では、do 記法構文はどのように機能するのdo {x <- [1,2,3]; return [x,x]}でしょうか。

<-は実際には単なる構文糖衣であるため、実際に を意味するのと同じように[1,2,3]1 : 2 : 3 : []上記の式は実際には を意味[1,2,3] >>= (\x -> return [x,x])し、これは に評価され、結果は にconcat (map (\x -> [[x,x]]) [1,2,3]))なり[1,1,2,2,3,3]ます。

>>=矢印が aとラムダにどのように変換されたかに注意してください。これは組み込みの (型クラスの) モナド関数のみを使用するため、一般的にどのモナドでも機能します。

上記のリストの例のラムダのように、提供する関数内で(>>=) :: Monad m => m a -> (a -> m b) -> m b「抽出された」を使用して操作することにより、値を抽出するふりをすることができます。aしかし、一般的な方法で実際にモナドから値を取得することは不可能>>=ですm b

于 2017-03-23T21:49:30.283 に答える