在玩了一些Idris及其效果教程示例之后,我终于想出了如何链接效果。不确定链是否是正确的单词,但我基本上是指用另一种方法实现的一种效果。
在这个例子中,我有一个效果,我称之为Lower。它直接调用IO。然后我有一个效果,我称之为高,我打算使用Lower实现其处理程序,而不是直接调用IO(或者就此而言,提到IO附近的任何地方)。
我终于解决了一个我无法解决的小问题:
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评论。如果我在where子句中移动lgreet定义,则无法编译,并显示以下错误消息:
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
然而,如果我将它保持在外面它工作正常,产生预期的输出:
greeting: hi
log: greeting received
farewell: bye
log: farewell received
答案 0 :(得分:2)
好的发现问题,idris在数据定义中推断此函数的类型有问题更高:
\_ => ()
明确指定类型可以解决问题:
data Higher : Effect where
HGreet : String -> Higher Unit Unit (the (Unit->Type) (\_ => ()))
HFarewell : String -> Higher () () (the (Unit->Type) (\_ => ()))