How can I find out which functions can be run on an expression? - haskell

I'd like to programmatically find out which functions in a module could possibly apply to a particular expression.
Let's make this concrete.
{-# LANGUAGE TemplateHaskell #-}
module Test where
-- we'll import template-haskell from Lens
-- so we can create prisms automatically for our 'AST'
import qualified Control.Lens.TH as LTH
--- some 'AST' in a toy language
data CExp
= CLit Int -- a literal integer
| CAdd CExp CExp -- addition
| CMul CExp CExp -- multiplication
| CSub CExp CExp -- subtraction
deriving Show
-- an eval for our AST
eval :: CExp -> Int
eval exp =
case exp of
CLit i -> i
CAdd e1 e2 ->
eval e1 + eval e2
CMul e1 e2 ->
eval e1 * eval e2
CSub e1 e2 ->
eval e1 - eval e2
-- a function to build a sum using add with our AST, from a list of Int values
listToSums :: [Int] -> CExp
listToSums =
foldr CAdd (CLit 0) . fmap CLit
-- here we make prisms for looking at particular values
-- in the CExp AST
LTH.makePrisms ''CExp
-- let's have an expression:
theList1 :: CExp
theList1 = listToSums [1..38]
Now, at this point, I'd like a function that can give me a list of all the top level functions of a particular module (including this one) that are able to be applied to the expression theList1. This will include the prisms that were created with makePrisms.
It would be fine if it uses the hint library's Interpreter monad. I've been experimenting with it a bit, and while I can get a list of all of the definitions at the top level of any module, and I can find the types of them, too (more or less), I'm a bit lost about how to pass an expression in as an argument to these functions then check if those expressions will typecheck.
If I can do that, I can run filter across all of the functions in a module, which lets me find out which ones are applicable.
Many thanks in advance.

Hint has a function called typeChecks :: MonadInterpreter m => String -> m Bool, which tells you whether the expression in the string is well typed in the interpreter's context.
fnsAccepting :: MonadInterpreter m => String -> m [Id]
fnsAccepting expr = do
moduleContents <- getLoadedModules >>= traverse getModuleExports
let importedFns = [fn | exports <- moduleContents, Fun fn <- exports]
filterM (\fn -> typeChecks $ fn ++ " " ++ parens expr) importedFns

Related

Getting all function arguments in haskel as list

Is there a way in haskell to get all function arguments as a list.
Let's supose we have the following program, where we want to add the two smaller numbers and then subtract the largest. Suppose, we can't change the function definition of foo :: Int -> Int -> Int -> Int. Is there a way to get all function arguments as a list, other than constructing a new list and add all arguments as an element of said list? More importantly, is there a general way of doing this independent of the number of arguments?
Example:
module Foo where
import Data.List
foo :: Int -> Int -> Int -> Int
foo a b c = result!!0 + result!!1 - result!!2 where result = sort ([a, b, c])
is there a general way of doing this independent of the number of arguments?
Not really; at least it's not worth it. First off, this entire idea isn't very useful because lists are homogeneous: all elements must have the same type, so it only works for the rather unusual special case of functions which only take arguments of a single type.
Even then, the problem is that “number of arguments” isn't really a sensible concept in Haskell, because as Willem Van Onsem commented, all functions really only have one argument (further arguments are actually only given to the result of the first application, which has again function type).
That said, at least for a single argument- and final-result type, it is quite easy to pack any number of arguments into a list:
{-# LANGUAGE FlexibleInstances #-}
class UsingList f where
usingList :: ([Int] -> Int) -> f
instance UsingList Int where
usingList f = f []
instance UsingList r => UsingList (Int -> r) where
usingList f a = usingList (f . (a:))
foo :: Int -> Int -> Int -> Int
foo = usingList $ (\[α,β,γ] -> α + β - γ) . sort
It's also possible to make this work for any type of the arguments, using type families or a multi-param type class. What's not so simple though is to write it once and for all with variable type of the final result. The reason being, that would also have to handle a function as the type of final result. But then, that could also be intepreted as “we still need to add one more argument to the list”!
With all respect, I would disagree with #leftaroundabout's answer above. Something being
unusual is not a reason to shun it as unworthy.
It is correct that you would not be able to define a polymorphic variadic list constructor
without type annotations. However, we're not usually dealing with Haskell 98, where type
annotations were never required. With Dependent Haskell just around the corner, some
familiarity with non-trivial type annotations is becoming vital.
So, let's take a shot at this, disregarding worthiness considerations.
One way to define a function that does not seem to admit a single type is to make it a method of a
suitably constructed class. Many a trick involving type classes were devised by cunning
Haskellers, starting at least as early as 15 years ago. Even if we don't understand their
type wizardry in all its depth, we may still try our hand with a similar approach.
Let us first try to obtain a method for summing any number of Integers. That means repeatedly
applying a function like (+), with a uniform type such as a -> a -> a. Here's one way to do
it:
class Eval a where
eval :: Integer -> a
instance (Eval a) => Eval (Integer -> a) where
eval i = \y -> eval (i + y)
instance Eval Integer where
eval i = i
And this is the extract from repl:
λ eval 1 2 3 :: Integer
6
Notice that we can't do without explicit type annotation, because the very idea of our approach is
that an expression eval x1 ... xn may either be a function that waits for yet another argument,
or a final value.
One generalization now is to actually make a list of values. The science tells us that
we may derive any monoid from a list. Indeed, insofar as sum is a monoid, we may turn arguments to
a list, then sum it and obtain the same result as above.
Here's how we can go about turning arguments of our method to a list:
class Eval a where
eval2 :: [Integer] -> Integer -> a
instance (Eval a) => Eval (Integer -> a) where
eval2 is i = \j -> eval2 (i:is) j
instance Eval [Integer] where
eval2 is i = i:is
This is how it would work:
λ eval2 [] 1 2 3 4 5 :: [Integer]
[5,4,3,2,1]
Unfortunately, we have to make eval binary, rather than unary, because it now has to compose two
different things: a (possibly empty) list of values and the next value to put in. Notice how it's
similar to the usual foldr:
λ foldr (:) [] [1,2,3,4,5]
[1,2,3,4,5]
The next generalization we'd like to have is allowing arbitrary types inside the list. It's a bit
tricky, as we have to make Eval a 2-parameter type class:
class Eval a i where
eval2 :: [i] -> i -> a
instance (Eval a i) => Eval (i -> a) i where
eval2 is i = \j -> eval2 (i:is) j
instance Eval [i] i where
eval2 is i = i:is
It works as the previous with Integers, but it can also carry any other type, even a function:
(I'm sorry for the messy example. I had to show a function somehow.)
λ ($ 10) <$> (eval2 [] (+1) (subtract 2) (*3) (^4) :: [Integer -> Integer])
[10000,30,8,11]
So far so good: we can convert any number of arguments into a list. However, it will be hard to
compose this function with the one that would do useful work with the resulting list, because
composition only admits unary functions − with some trickery, binary ones, but in no way the
variadic. Seems like we'll have to define our own way to compose functions. That's how I see it:
class Ap a i r where
apply :: ([i] -> r) -> [i] -> i -> a
apply', ($...) :: ([i] -> r) -> i -> a
($...) = apply'
instance Ap a i r => Ap (i -> a) i r where
apply f xs x = \y -> apply f (x:xs) y
apply' f x = \y -> apply f [x] y
instance Ap r i r where
apply f xs x = f $ x:xs
apply' f x = f [x]
Now we can write our desired function as an application of a list-admitting function to any number
of arguments:
foo' :: (Num r, Ord r, Ap a r r) => r -> a
foo' = (g $...)
where f = (\result -> (result !! 0) + (result !! 1) - (result !! 2))
g = f . sort
You'll still have to type annotate it at every call site, like this:
λ foo' 4 5 10 :: Integer
-1
− But so far, that's the best I can do.
The more I study Haskell, the more I am certain that nothing is impossible.

Pattern matching on a private data constructor

I'm writing a simple ADT for grid axis. In my application grid may be either regular (with constant step between coordinates), or irregular (otherwise). Of course, the regular grid is just a special case of irregular one, but it may worth to differentiate between them in some situations (for example, to perform some optimizations). So, I declare my ADT as the following:
data GridAxis = RegularAxis (Float, Float) Float -- (min, max) delta
| IrregularAxis [Float] -- [xs]
But I don't want user to create malformed axes with max < min or with unordered xs list. So, I add "smarter" construction functions which perform some basic checks:
regularAxis :: (Float, Float) -> Float -> GridAxis
regularAxis (a, b) dx = RegularAxis (min a b, max a b) (abs dx)
irregularAxis :: [Float] -> GridAxis
irregularAxis xs = IrregularAxis (sort xs)
I don't want user to create grids directly, so I don't add GridAxis data constructors into module export list:
module GridAxis (
GridAxis,
regularAxis,
irregularAxis,
) where
But it turned out that after having this done I cannot use pattern matching on GridAxis anymore. Trying to use it
import qualified GridAxis as GA
test :: GA.GridAxis -> Bool
test axis = case axis of
GA.RegularAxis -> True
GA.IrregularAxis -> False
gives the following compiler error:
src/Physics/ImplicitEMC.hs:7:15:
Not in scope: data constructor `GA.RegularAxis'
src/Physics/ImplicitEMC.hs:8:15:
Not in scope: data constructor `GA.IrregularAxis'
Is there something to work this around?
You can define constructor pattern synonyms. This lets you use the same name for smart construction and "dumb" pattern matching.
{-# LANGUAGE PatternSynonyms #-}
module GridAxis (GridAxis, pattern RegularAxis, pattern IrregularAxis) where
import Data.List
data GridAxis = RegularAxis_ (Float, Float) Float -- (min, max) delta
| IrregularAxis_ [Float] -- [xs]
-- The line with "<-" defines the matching behavior
-- The line with "=" defines the constructor behavior
pattern RegularAxis minmax delta <- RegularAxis_ minmax delta where
RegularAxis (a, b) dx = RegularAxis_ (min a b, max a b) (abs dx)
pattern IrregularAxis xs <- IrregularAxis_ xs where
IrregularAxis xs = IrregularAxis_ (sort xs)
Now you can do:
module Foo
import GridAxis
foo :: GridAxis -> a
foo (RegularAxis (a, b) d) = ...
foo (IrregularAxis xs) = ...
And also use RegularAxis and IrregularAxis as smart constructors.
This looks as a use case for pattern synonyms.
Basically you don't export the real constructor, but only a "smart" one
{-# LANGUAGE PatternSynonyms #-}
module M(T(), SmartCons, smartCons) where
data T = RealCons Int
-- the users will construct T using this
smartCons :: Int -> T
smartCons n = if even n then RealCons n else error "wrong!"
-- ... and destruct T using this
pattern SmartCons n <- RealCons n
Another module importing M can then use
case someTvalue of
SmartCons n -> use n
and e.g.
let value = smartCons 23 in ...
but can not use the RealCons directly.
If you prefer to stay in basic Haskell, without extensions, you can use a "view type"
module M(T(), smartCons, Tview(..), toView) where
data T = RealCons Int
-- the users will construct T using this
smartCons :: Int -> T
smartCons n = if even n then RealCons n else error "wrong!"
-- ... and destruct T using this
data Tview = Tview Int
toView :: T -> Tview
toView (RealCons n) = Tview n
Here, users have full access to the view type, which can be constructed/destructed freely, but have only a restricted start constructor for the actual type T. Destructing the actual type T is possible by moving to the view type
case toView someTvalue of
Tview n -> use n
For nested patterns, things become more cumbersome, unless you enable other extensions such as ViewPatterns.

What does '#' mean in Haskell?

I've tried googling but come up short. I am furthering my Haskell knowledge by reading some articles and I came across one that uses a syntax I've never seen before.
An example would be:
reconstruct node#(Node a b c l r) parent#(Node b d le ri)
I've never seen these #'s before. I tried searching online for an answer but came up short. Is this simply a way to embed tags to help make things clearer, or do they have an actual impact on the code?
It is used in pattern matching. Now node variable will refer to the entire Node data type for the argument Node a b c l r. So instead of passing to the function as Node a b c l r, you can use node instead to pass it up.
A much simpler example to demonstrate it:
data SomeType = Leaf Int Int Int | Nil deriving Show
someFunction :: SomeType -> SomeType
someFunction leaf#(Leaf _ _ _) = leaf
someFunction Nil = Leaf 0 0 0
The someFunction can also be written as:
someFunction :: SomeType -> SomeType
someFunction (Leaf x y z) = Leaf x y z
someFunction Nil = Leaf 0 0 0
See how simpler was the first version ?
Using #t as a type indicator
Besides the argument pattern matching usage described in the answer of #Sibi, in Haskell the "at" character ('#', also known as an arobase character) can be used in some contexts to force a typing decision. This is mentioned in the comments by #Josh.F.
This is not part of the default language features, and is known as the Type Application Haskell language extension. In summary, the extension allows you to give explicit type arguments to a polymorphic function such as read. In a classic .hs source file, the relevant pragma must be included:
{-# LANGUAGE TypeApplications #-}
Example:
$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
λ>
λ> let x = (read #Integer "33")
<interactive>:4:10: error:
Pattern syntax in expression context: read#Integer
Did you mean to enable TypeApplications?
λ>
λ> :set -XTypeApplications
λ>
λ> let x = (read #Integer "33")
λ>
λ> :type x
x :: Integer
λ>
λ> x
33
λ>
Further details
For the read polymorphic function, the type indicator introduced by # relates to the type of the result returned by read. But this is not generally true.
Generally speaking, you have to consider the type variables that appear in the type signature of the function at hand. For example, let's have a look at the fmap library function.
fmap :: Functor ft => (a -> b) -> ft a -> ft b
So here, we have 3 type variables, in order of appearance: ft, a, b. If we specialize fmap like this:
myFmap = fmap #type1 #type2 #type3
then type1 will relate to ft, type2 will relate to a and type3 will relate to b. Also, there is a special dummy type indicator #_ which means: “here, any type goes”.
For example, we can force the output type of fmap to be Integer and the functor to be the plain list [], leaving the input type a unspecified:
λ>
λ> myFmap = fmap #[] #_ #Integer
λ>
λ> :type myFmap
myFmap :: (_ -> Integer) -> [_] -> [Integer]
λ>
As for the read function, its type is:
read :: Read a => String -> a
So there is only room for one type indicator, and it relates to the type of the result returned by read, as displayed above.

Haskell Monads Either

I have a little problem with Data Types in Haskell, I think I should post first some code to help to understand the problem
helper :: (MonadMask a, MonadIO a, Functor a) => Expr -> String -> a (Either InterpreterError Int)
helper x y = ( getEval ( mkCodeString x y ) )
-- Creates Code String
mkCodeString :: (Show a) => a -> String -> String
mkCodeString x y = unpack (replace (pack "Const ") (pack "") (replace (pack "\"") (pack "") (replace (pack "Add") (pack y) (pack (show x) ) ) ) )
-- Calculates String
getEval :: (MonadMask m, MonadIO m, Functor m) => [Char] -> m (Either InterpreterError Int)
getEval str = (runInterpreter (setImports ["Prelude"] >> interpret str (as ::Int)))
-- | A test expression.
testexpression1 :: Expr
testexpression1 = 3 + (4 + 5)
-- | A test expression.
testexpression2 :: Expr
testexpression2 = (3 + 4) + 5
-- | A test expression.
testexpression3 :: Expr
testexpression3 = 2 + 5 + 5
I use the helper Function like this "helper testexpression3 "(+)" and it returns me the value "Right 12" with the typ "Either InterpreterError Int", but I only want to have the "Int" value "12"
I tried the function -> "getValue (Right x) = x" but I dont get that Int value.
After some time of testing I think it is a problem with the Monads I've used.
If I test the typ of the helper function like this: ":t (helper testexpression1 "(+)")" I'll get that: "(... :: (Functor a, MonadIO a, MonadMask a) => a (Either InterpreterError Int)"
How can I make something like that working:
write "getValue (helper testexpression1 "(+)")" and get "12" :: Int
I'll know that the code makes no sence, but its a homework and I wanted to try some things with haskell.Hope you have some more Ideas than I am.
And Sorry for my bad English, I have began to learn English, but I am just starting and Thank you for every Idea and everything.
Edit, here is what was missing on code:
import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?))
import Data.Function (on)
import Language.Haskell.Interpreter -- Hint package
import Data.Text
import Data.Text.Encoding
import Data.ByteString (ByteString)
import Control.Monad.Catch
-- | A very simple data type for expressions.
data Expr = Const Int | Add Expr Expr deriving Show
-- | 'Expression' is an instance of 'Num'. You will get warnings because
-- many required methods are not implemented.
instance Num Expr where
fromInteger = Const . fromInteger
(+) = Add
-- | Equality of 'Expr's modulo associativity.
instance Eq Expr where
(==) x1 x2 = True --(helper x1 "(+)") == (helper x2 "(+)") && (helper x1 "(*)") == (helper x2 "(*)")
That functions are also in the file ... everything else I have in my file are some Testcases I have created for me.
helper textExpr "(+)" is not of type Either InterpreterError Int it is of type (MonadMask a, MonadIO a, Functor a) => a (Either InterpreterError Int). This later tyoe can be treated as if it was IO (Either InterpreterError Int) for our purposes.
In general something of type IO a (e.g. IO (Either InterpreterError Int)) doesn't contain, in the strictest sense, a value of type a, so you can't just extract a value willy-nilly. Something of type IO a is an action, that when performed, will produce a value of type a. Haskell only performs one action, the one called main. That said, it allows us to easily build larger actions out of smaller actions.
main = helper textExpr "(+)" >>= print
That operator there (>>=) is a monadic bind. For more information about monads in general, see You Could Have Invented Monads!. For an idea of how the IO Monad might be constructed see Free Monads for Less (Part 3 of 3): Yielding IO (under "Who Needs the RealWorld?") or Idris' implementation of IO -- but keep in mind that the IO Monad is opaque and abstract in Haskell; don't expect to be able to get an a value from an IO a value unless you are writing main (an application).

Haskell: how to write a monadic variadic function, with parameters using the monadic context

I'm trying to make a variadic function with a monadic return type, whose parameters also require the monadic context. (I'm not sure how to describe that second point: e.g. printf can return IO () but it's different in that its parameters are treated the same whether it ends up being IO () or String.)
Basically, I've got a data constructor that takes, say, two Char parameters. I want to provide two pointer style ID Char arguments instead, which can be automagically decoded from an enclosing State monad via a type class instance. So, instead of doing get >>= \s -> foo1adic (Constructor (idGet s id1) (idGet s id2)), I want to do fooVariadic Constructor id1 id2.
What follows is what I've got so far, Literate Haskell style in case somebody wants to copy it and mess with it.
First, the basic environment:
> {-# LANGUAGE FlexibleContexts #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE MultiParamTypeClasses #-}
> import Control.Monad.Trans.State
> data Foo = Foo0
> | Foo1 Char
> | Foo2 Bool Char
> | Foo3 Char Bool Char
> deriving Show
> type Env = (String,[Bool])
> newtype ID a = ID {unID :: Int}
> deriving Show
> class InEnv a where envGet :: Env -> ID a -> a
> instance InEnv Char where envGet (s,_) i = s !! unID i
> instance InEnv Bool where envGet (_,b) i = b !! unID i
Some test data for convenience:
> cid :: ID Char
> cid = ID 1
> bid :: ID Bool
> bid = ID 2
> env :: Env
> env = ("xy", map (==1) [0,0,1])
I've got this non-monadic version, which simply takes the environment as the first parameter. This works fine but it's not quite what I'm after. Examples:
$ mkFoo env Foo0 :: Foo
Foo0
$ mkFoo env Foo3 cid bid cid :: Foo
Foo3 'y' True 'y'
(I could use functional dependencies or type families to get rid of the need for the :: Foo type annotations. For now I'm not fussed about it, since this isn't what I'm interested in anyway.)
> mkFoo :: VarC a b => Env -> a -> b
> mkFoo = variadic
>
> class VarC r1 r2 where
> variadic :: Env -> r1 -> r2
>
> -- Take the partially applied constructor, turn it into one that takes an ID
> -- by using the given state.
> instance (InEnv a, VarC r1 r2) => VarC (a -> r1) (ID a -> r2) where
> variadic e f = \aid -> variadic e (f (envGet e aid))
>
> instance VarC Foo Foo where
> variadic _ = id
Now, I want a variadic function that runs in the following monad.
> type MyState = State Env
And basically, I have no idea how I should proceed. I've tried expressing the type class in different ways (variadicM :: r1 -> r2 and variadicM :: r1 -> MyState r2) but I haven't succeeded in writing the instances. I've also tried adapting the non-monadic solution above so that I somehow "end up" with an Env -> Foo which I could then easily turn into a MyState Foo, but no luck there either.
What follows is my best attempt thus far.
> mkFooM :: VarMC r1 r2 => r1 -> r2
> mkFooM = variadicM
>
> class VarMC r1 r2 where
> variadicM :: r1 -> r2
>
> -- I don't like this instance because it requires doing a "get" at each
> -- stage. I'd like to do it only once, at the start of the whole computation
> -- chain (ideally in mkFooM), but I don't know how to tie it all together.
> instance (InEnv a, VarMC r1 r2) => VarMC (a -> r1) (ID a -> MyState r2) where
> variadicM f = \aid -> get >>= \e -> return$ variadicM (f (envGet e aid))
>
> instance VarMC Foo Foo where
> variadicM = id
>
> instance VarMC Foo (MyState Foo) where
> variadicM = return
It works for Foo0 and Foo1, but not beyond that:
$ flip evalState env (variadicM Foo1 cid :: MyState Foo)
Foo1 'y'
$ flip evalState env (variadicM Foo2 cid bid :: MyState Foo)
No instance for (VarMC (Bool -> Char -> Foo)
(ID Bool -> ID Char -> MyState Foo))
(Here I would like to get rid of the need for the annotation, but the fact that this formulation needs two instances for Foo makes that problematic.)
I understand the complaint: I only have an instance that goes from Bool ->
Char -> Foo to ID Bool -> MyState (ID Char -> Foo). But I can't make the
instance it wants because I need MyState in there somewhere so that I can
turn the ID Bool into a Bool.
I don't know if I'm completely off track or what. I know that I could solve my basic issue (I don't want to pollute my code with the idGet s equivalents all over the place) in different ways, such as creating liftA/liftM-style functions for different numbers of ID parameters, with types like (a -> b -> ... -> z -> ret) -> ID a -> ID b -> ... -> ID z -> MyState ret, but I've spent too much time thinking about this. :-) I want to know what this variadic solution should look like.
WARNING
Preferably don't use variadic functions for this type of work. You only have a finite number of constructors, so smart constructors don't seem to be a big deal. The ~10-20 lines you would need are a lot simpler and more maintainable than a variadic solution. Also an applicative solution is much less work.
WARNING
The monad/applicative in combination with variadic functions is the problem. The 'problem' is the argument addition step used for the variadic class. The basic class would look like
class Variadic f where
func :: f
-- possibly with extra stuff
where you make it variadic by having instances of the form
instance Variadic BaseType where ...
instance Variadic f => Variadic (arg -> f) where ...
Which would break when you would start to use monads. Adding the monad in the class definition would prevent argument expansion (you would get :: M (arg -> f), for some monad M). Adding it to the base case would prevent using the monad in the expansion, as it's not possible (as far as I know) to add the monadic constraint to the expansion instance. For a hint to a complex solution see the P.S..
The solution direction of using a function which results in (Env -> Foo) is more promising. The following code still requires a :: Foo type constraint and uses a simplified version of the Env/ID for brevity.
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies #-}
module Test where
data Env = Env
data ID a = ID
data Foo
= Foo0
| Foo1 Char
| Foo2 Char Bool
| Foo3 Char Bool Char
deriving (Eq, Ord, Show)
class InEnv a where
resolve :: Env -> ID a -> a
instance InEnv Char where
resolve _ _ = 'a'
instance InEnv Bool where
resolve _ _ = True
The Type families extension is used to make the matching stricter/better. Now the variadic function class.
class MApp f r where
app :: Env -> f -> r
instance MApp Foo Foo where
app _ = id
instance (MApp r' r, InEnv a, a ~ b) => MApp (a -> r') (ID b -> r) where
app env f i = app env . f $ resolve env i
-- using a ~ b makes this instance to match more easily and
-- then forces a and b to be the same. This prevents ambiguous
-- ID instances when not specifying there type. When using type
-- signatures on all the ID's you can use
-- (MApp r' r, InEnv a) => MApp (a -> r') (ID a -> r)
-- as constraint.
The environment Env is explicitly passed, in essence the Reader monad is unpacked preventing the problems between monads and variadic functions (for the State monad the resolve function should return a new environment). Testing with app Env Foo1 ID :: Foo results in the expected Foo1 'a'.
P.S.
You can get monadic variadic functions to work (to some extent) but it requires bending your functions (and mind) in some very strange ways. The way I've got such things to work is to 'fold' all the variadic arguments into a heterogeneous list. The unwrapping can then be done monadic-ally. Though I've done some things like that, I strongly discourage you from using such things in actual (used) code as it quickly gets incomprehensible and unmaintainable (not to speak of the type errors you would get).

Resources