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

`raise` an arbitrary number of times #28

Closed jgrosso closed 5 years ago

jgrosso commented 5 years ago

Apologies if there is a basic resolution to the issue.

Is there a way to call one action inside another, if the called action has only a subset of the caller's effects? For example, something with type foo :: (Members subset superset) => Eff subset () -> Eff superset ().

The following fails to compile, since (obviously) subset ~ superset is not true:

foo :: (Members subset superset) => Eff subset () -> Eff superset ()
foo = id
-- Could not deduce: subset ~ superset from the context...

and the following also doesn't typecheck because AFAICT raise is too concrete, requiring something of the form eff ': subset:

foo :: (Members subset superset) => Eff subset () -> Eff superset ()
foo = raise . id
-- Could not deduce: superset ~ (e0 : subset) from the context...

If worse comes to worse, I can make all my types concrete and use raise as many times as necessary, but I'm hoping there's a solution that doesn't require such premature specialization.

(Thanks for your work on freer-simple, it's a wonderful library!)

EDIT: Fixed a typo in the second code example.

jgrosso commented 5 years ago

Likely solution at https://github.com/polysemy-research/polysemy/issues/188