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

Trouble using makeEffect on a GADT with nested variables in the type constructor #16

Closed andremarianiello closed 5 years ago

andremarianiello commented 5 years ago

I ran into an issue when running a program like this

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
module Main where

import Control.Monad.Freer.TH

main :: IO ()
main = return ()

data Test a where
  Test :: forall b. Maybe b -> Test ()

makeEffect ''Test

The error was:

    /root/tmp/app/Main.hs:16:1: error:
        The exact Name ‘b_XC7’ is not in scope
          Probable cause: you used a unique Template Haskell name (NameU),
          perhaps via newName, but did not bind it
          If that's it, then -ddump-splices might be useful
       |
    16 | makeEffect ''Test
       | ^^^^^^^^^^^^^^^^^

and the splices were

app/Main.hs:16:1-17: Splicing declarations
    makeEffect ''Test
  ======>
    test ::
      forall effs_a46Q.
      Data.OpenUnion.Internal.Member Test effs_a46Q =>
      Maybe b_XC7 -> Control.Monad.Freer.Internal.Eff effs_a46Q ()
    test a_a46R = Control.Monad.Freer.Internal.send (Test a_a46R)

It seems like makeEffect tries to determine what variables to stick in the context of the generated function by pulling our top-level type variables (i.e. VarT) from the constructor, but Maybe b is not a VarT so it gets missed.