3
少しのIdrisとそのエフェクトのチュートリアルの例を演奏した後、私は最終的にどのように連鎖するのかを考え出しました。鎖が正しい単語であるかどうかはわかりませんが、基本的には別の意味で1つの効果が実装されていることを意味します。Idrisの連鎖効果
この例では、Lowerと呼ぶエフェクトがあります。直接IOを呼び出します。それから私はHigherと呼ぶEffectを持っています。私は、IOを直接呼び出すのではなく、Lowerを使ってハンドラを実装しようと考えています。
私は最終的にそれは私が把握カント小さな問題で動作するようになった:
module Main
import Effects
data Lower : Effect where
LLog : String -> Lower()() (\_ =>())
LGreet : String -> Lower()() (\_ =>())
LFarewell : String -> Lower()() (\_ =>())
Handler Lower IO where
handle _ (LLog msg) k = do
putStrLn $ "log: " ++ msg
k()()
handle _ (LGreet msg) k = do
putStrLn $ "greeting: " ++ msg
k()()
handle _ (LFarewell msg) k = do
putStrLn $ "farewell: " ++ msg
k()()
LOWER : EFFECT
LOWER = MkEff() Lower
data Higher : Effect where
HGreet : String -> Higher()() (\_ =>())
HFarewell : String -> Higher()() (\_ =>())
lgreet : String -> Eff() [LOWER]
lgreet msg = do
call $ LGreet msg
call $ LLog "greeting received"
lfarewell : String -> Eff() [LOWER]
lfarewell msg = do
call $ LFarewell msg
call $ LLog "farewell received"
(Monad m, Handler Lower m) => Handler Higher m where
handle _ (HGreet msg) k =
do
runInit [()] (lgreet msg)
k()()
{- FIXME: This doesnt work, why ?
where
lgreet : String -> Eff() [LOWER]
lgreet msg = do
call $ LGreet msg
call $ LLog "greeting received"
-}
handle _ (HFarewell msg) k =
do
runInit [()] (lfarewell msg)
k()()
HIGHER : EFFECT
HIGHER = MkEff() Higher
dummy : Eff() [HIGHER]
dummy = do
call $ HGreet "hi"
call $ HFarewell "bye"
main : IO()
main = do
runInit [()] dummy
は、私が上記の作っFIXMEコメントを参照してください。
When checking type of Effects.Main.Higher, m implementation of Effects.Handler, method handle, lgreet:
Type mismatch between
() (Type of (\underscore =>()) x)
and
Type (Expected type)
chain1.idr:64:6:When checking right hand side of main with expected type
IO()
Can't find implementation for Handler Higher IO
はそれが正常に動作外で、私はそれを維持する場合のに対して、意図した出力を生成します:私は、where句内のlgreet定義を移動した場合、それは次のエラーメッセージでコンパイルに失敗し
greeting: hi
log: greeting received
farewell: bye
log: farewell received
関連:関数の宣言を避けたい場合は、 'runInit [...] $ do ...'を実行できます。しかし、このネストされたdo内のエフェクトのタイプを制限する必要がある場合、不正確/不適切な推論のために '(Eff foo [BAR])'を実行すると失敗するでしょう。 '(EffM m foo [BAR](\ _ = > ..)) '、ofcはハンドラ宣言で使用している変数とmを置き換えます。 – RKS