私は、次のしているコードスニペットのように思えるし、それを設定することができませんでした:唯一の番号を与え、バックタイプの署名などを取得することが可能である方法型推論は、それがどのように動作するか、魔法
embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int
embedded = return 1
?コンパイラはどのようにそれを行うのですか?
私は、次のしているコードスニペットのように思えるし、それを設定することができませんでした:唯一の番号を与え、バックタイプの署名などを取得することが可能である方法型推論は、それがどのように動作するか、魔法
embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int
embedded = return 1
?コンパイラはどのようにそれを行うのですか?
文句の選択は少し残念です。式return 1
がのタイプシグネチャMaybeT (ExceptT String (ReaderT() IO)) Int
を返すことはありません。
n.m。
Prelude> embedded = return 1
Prelude> :type embedded
embedded :: (Num a, Monad m) => m a
型に注釈を付けることで、あなたは明示的にあなたがそれよりも少ない一般的な何かをしたいと述べている:あなたがタイプを指定しない場合、式ははるかに一般的であり、コメントに書いています。
具体的には、タイプがMaybeT (ExceptT String (ReaderT() IO)) Int
であると述べています。
return
はどのように機能しますか? lift
はMonadTrans
とリフトによって定義されるのに対し、
return = lift . return
右側return
はMonad
「インナー」に属するreturn
関数である:MaybeT m a
はm
がMonad
であり、そしてreturn
このように定義されている場合Monad
あります基本的なモナド値はMaybeT
までです。
これは、MaybeT
値がどのように作成されたかを説明しますが、全体の話ではありません。この場合
、Monad
'内側' は(実際には、別のMonadTrans
)別のMonad
ある、ExceptT String (ReaderT() IO)
あります。 return
は、このように定義される:右側return
はまだ別のネストされたMonad
属する場合、これは、別のネストされたreturn
ある
return a = ExceptT $ return (Right a)
注意こと。
この場合、ネストされたMonad
はReaderT() IO
- 別のMonadTrans
です。右側return
(この特定の場合)IO
のために定義されreturn
ある
return = lift . return
さらに別のネストreturn
、:それはこのようreturn
を定義します。
このすべてはa
でパラメータ化されています。この場合、Int
に制限されています。
したがってreturn 1
は、最初に純粋な値1
をとり、それをIO Int
にパッケージします。これはReaderT() IO Int
に持ち上げられ、再びExceptT String (ReaderT() IO) Int
にパッケージされます。最後に、この値はMaybeT
に持ち上げられます。
恐縮です。 –
あなたは 'return'を忘れています。'return'はキーワードではなく、関数です:' return :: Monad m => a - > m a'です。 –
あなたは正しいです。コンパイラは* this *型の署名を推論しません。それははるかに一般的なものを推論するでしょう。 *あなたはコンパイラに伝えるためにあまり一般的でない署名を提供します。 "ねえ、私がやっていることを知っている、私はこれが欲しい"。 –
しかしイメージングの仕方はどうですか? –