2017-09-25 20 views
3

私は、次のしているコードスニペットのように思えるし、それを設定することができませんでした:唯一の番号を与え、バックタイプの署名など​​を取得することが可能である方法型推論は、それがどのように動作するか、魔法

embedded :: MaybeT (ExceptT String (ReaderT() IO)) Int 
embedded = return 1 

?コンパイラはどのようにそれを行うのですか?

+0

あなたは 'return'を忘れています。'return'はキーワードではなく、関数です:' return :: Monad m => a - > m a'です。 –

+2

あなたは正しいです。コンパイラは* this *型の署名を推論しません。それははるかに一般的なものを推論するでしょう。 *あなたはコンパイラに伝えるためにあまり一般的でない署名を提供します。 "ねえ、私がやっていることを知っている、私はこれが欲しい"。 –

+0

しかしイメージングの仕方はどうですか? –

答えて

10

文句の選択は少し残念です。式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はどのように機能しますか? liftMonadTransとリフトによって定義されるのに対し、

return = lift . return 

右側returnMonad「インナー」に属するreturn関数である:MaybeT m amMonadであり、そしてreturnこのように定義されている場合Monadあります基本的なモナド値はMaybeTまでです。

これは、MaybeT値がどのように作成されたかを説明しますが、全体の話ではありません。この場合

Monad '内側' は(実際には、別のMonadTrans)別のMonadある、ExceptT String (ReaderT() IO)あります。 returnは、このように定義される:右側returnはまだ別のネストされたMonad属する場合、これは、別のネストされたreturnある

return a = ExceptT $ return (Right a) 

注意こと。

この場合、ネストされたMonadReaderT() 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に持ち上げられます。

+0

恐縮です。 –

関連する問題