伊德里斯的链式效应

时间:2016-09-05 20:40:08

标签: idris

在玩了一些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

1 个答案:

答案 0 :(得分:2)

好的发现问题,idris在数据定义中推断此函数的类型有问题更高:

\_ => ()

明确指定类型可以解决问题:

data Higher : Effect where

  HGreet : String -> Higher Unit Unit (the (Unit->Type) (\_ => ()))
  HFarewell : String -> Higher () () (the (Unit->Type) (\_ => ()))