lexi-lambda / freer-simple

A friendly effect system for Haskell
https://hackage.haskell.org/package/freer-simple
BSD 3-Clause "New" or "Revised" License
227 stars 19 forks source link

Add TH makeFreer for generating effects from a GADT #15

Closed Tehnix closed 5 years ago

Tehnix commented 5 years ago

I wanted to get rid of the tedious step of generating all the send... functions for the effect GADTs, and saw that a PR to freer-effects had been lying around with all the work for quite some time (and the project is now dead).

This is my attempt at porting it to freer-simple, here. The code is basically the same, although I added a trivial test to check if the generated function was doing its job.

Let me know if this is not something you want added here, or if there are some changes that need to be made :)

The usage is quite simple (extracted from the test),

{-# LANGUAGE TemplateHaskell #-}
import Control.Monad.Freer (Eff, run, interpret, type(~>))
import Control.Monad.Freer.TH (makeFreer)

-- Create a test GADT for our effects.
data Prepender next where
  PrependSomething :: String -> Prepender String

-- Make TH generate our effect functions.
makeFreer ''Prepender

-- And now we can use it as any other manually generated effects.
runPrepender :: Eff (Prepender ': effs) ~> Eff effs
runPrepender = interpret
  (\case
  PrependSomething s -> pure $ "prepended: " ++ s
  )

testGeneratedFunction :: String -> String
testGeneratedFunction s = run . runPrepender $ prependSomething s
Tehnix commented 5 years ago

Thanks for taking the time to look at this! :)

I arrived at the constraints template-haskell >= 2.11 && < 2.15 by doing the following: I tested a resolvers from nightly-2018-10-23 to lts-7 (just going from the travis build matrix), and it seems it should at least work with the current template-haskell used in nightly, which is 2.14. I've also put the lower bound on what LTS 7 uses, which is 2.11.

I think the name change make sense too, so I've changed it to makeEffect as suggested :) One thing (bike-shedding), should it be singular or plural? I.e. makeEffects? I have no strong opinion towards either.