Justin Bailey | 17 Jul 22:43 2014
Picon

Extensible Effects & Multiple Operations

I am playing around with the extensible-effects framework and cannot
figure out how to solve this problem. I am trying to define a set of
operations that only work after a file has been opened. For example,
reading a character from a file or detecting EOF.

My problem is I cannot figure out how to define one "runner" for my
Effect that can deal with operations with different result types. For
example, I would like my `readFrom` and `atEOF` operations to have the
following types:

  data OpenFile r v =  ... -- my "OpenFile" effect

  -- read a character from the file
  readFrom :: Eff r Char

  -- detect EOF
  atEOF :: Eff r Bool

And I would like to use this operations as follows (where I read a
byte from the file, check EOF, and return the concatenation of the two
values):

  main = do
     c <- runOpenFile "Setup.hs" (do
        a <- readFrom -- `a` has `Char` type
        eof <- atEOF -- `eof` has `Bool` type
        return $ [a] ++ show eof)
     putStrLn c

However, I cannot define a `runOpenFile` that compiles. For example,
(Continue reading)

Tobias Florek | 18 Jul 00:32 2014
Picon

Re: Extensible Effects & Multiple Operations

hi,

 > My problem is I cannot figure out how to define one "runner" for my
> Effect that can deal with operations with different result types.

afaict you have two possibilities.

  * `OpenFile` is essentially a `Reader Handle` and
`readFrom :: (SetMember Lift IO r, Member OpenFile r) => Eff r Char` 
asks for the handle and works with that (in `IO`).

  * if you don't want to impose `SetMember Lift IO`, you will have to 
live with a sum type in your `OpenFile`, but not with `Result`. just use

     data OpenFile v = Read (Char -> v)
                     | EOF  (Bool -> v)
       deriving Typeable

btw: i find working with `ScopedTypeVariables` easier than using your 
`asTypeOf`. but even then, you should maybe define your own

     prj' :: Union (OpenFile :> r) (VE (OpenFile :> r) result) -> Maybe 
(OpenFile (VE (OpenFile :> r) result))
     prj' = prj

iff you really need it, which you don't in this example.

have fun with extensible effects,
  tob
(Continue reading)

Justin Bailey | 21 Jul 18:02 2014
Picon

Re: Extensible Effects & Multiple Operations

On Thu, Jul 17, 2014 at 3:32 PM, Tobias Florek <haskell <at> ibotty.net> wrote:
>     data OpenFile v = Read (Char -> v)
>                     | EOF  (Bool -> v)
>       deriving Typeable
>

That worked! Removing the type variable (`a`) from `OpenFile` did the
trick. I was carrying too much type information around for what I
wanted to do (e.g., OpenFile Char and OpenFile Bool). Removing that
extra piece of info allowed me to write `runOpenFile` just like I
wanted.

Thanks!

Justin

Gmane