7

次の構成がどのように機能するかについての説明を探しているだけです。

(=<<) . return

どこ

(=<<) ::       (a -> m b) -> m a -> m b
return :: a -> m a
(.) :: (b -> c) -> (a -> b) -> a -> c

最終的なタイプ:

GHCi> :t (=<<) . return
(=<<) . return :: Monad m => m b -> m a -> m b

ma(a-> mb)とどのように一致させることができるか理解できません。関数型を期待する(= <<)の最初の引数に単純型であるreturnの結果をどのように適用できますか?

4

2 に答える 2

7

説明は次のとおりです。

  1. あなたreturnは(おそらく予期せずに)あなたとは異なるモナドです=<<
  2. 使用するモナドはリーダーモナド(->) rです。

コンパイラはreturn :: c -> m' c、の最初の引数での結果を統合しようとする(a -> m b) -> m a -> m bため、。で統合 m' ca -> m bます。唯一の可能性は、それがいくつかm'のリーダーモナドであるということです。次に、との統合を試みます(プレフィックス表記に変換されます) 。これは、とに設定することで解決されます。したがって、統合後、コンパイラは最も一般的なタイプを取得します(->) rr(->) r c(->) a (m b)racm b

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

または通常の中置記法で

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

参照:


編集:モナドを定義するには、(部分的に適用された)タイプの種類 * -> *が必要です。これらはほとんどの場合部分的に適用されるデータコンストラクターですが、この特定のケースでは、->2つの型引数を取り、新しい型(関数型)を作成する型演算子と見なします。したがって、任意のタイプrに対して、部分的に適用される式(->) rは一種のタイプです* -> *。結局のところ、モナド操作を説明する簡単な方法があります。Control.Readerモナドと それを説明するこの記事も参照してください。のモナド操作はReader、のとまったく同じ方法で実装されますが(->)、唯一の違いはReader、操作を個別のデータ型にラップすることです。

于 2012-08-19T09:10:25.007 に答える
1

もう一度、落書きをして、視覚的な理解を助けるために物を並べて置きます:

g = ((=<<) . return)   {-

((=<<) . return) x y 
         ===   (=<<)    (return x)    y               return :: a' -> m' a'
               (=<<) :: (a -> m b) -> m a -> m b      return x :: m' a' , x :: a'
                          m'  a'                      m' ~ ((->) a) , a' ~ m b 

return x === const x             -- instance Monad ((->) a) where return = const
g x y === y >>= (\_ -> x) === y >> x   (!!)
-}

g :: m b -> m a -> m b

結局のところ(そしておそらく型シグネチャから明らかでした)g === flip (>>)、:

Prelude> ((=<<).return) [1] "xyz"   -- ===  (=<<) (const [1]) "xyz" 
                                    -- ===  "xyz" >>= const [1]
                                    -- ===  "xyz" >> [1]
                                    -- ===  (>> [1]) "xyz"
[1,1,1]
于 2012-08-20T09:21:33.603 に答える