Non type-variable argument in the constraint: MonadError Failure m - haskell

I have defined a custom error type:
data Failure = NetworkError Message |
UserIsTooStupid Message |
InvalidOperation Message |
UnexpectedError Message
type Message = String
I am trying to use MonadError with my error type:
loadJSON :: (Aeson.FromJSON v, MonadIO m, MonadError Failure m) => URI -> m v
loadJSON uri = do
body <- liftIO $ getResponseBody =<< simpleHTTP (getRequest uri)
case Aeson.decode body of
Just json -> return json
Nothing -> throwError $ SerialisationError "Couldn't deserialise from JSON"
type URI = String
In other words, this function can return any monad which satisfies both MonadIO and MonadError, but the only type of error it can throw is Failure.
This fails to compile, with the error message:
Non type-variable argument in the constraint: MonadError Failure m
(Use -XFlexibleContexts to permit this)
In the type signature for `loadJSON':
loadJSON :: (Aeson.FromJSON v, MonadIO m, MonadError Failure m) =>
URI -> m v
GHC wants me to turn on the FlexibleContexts language extension to make this code work. What does FlexibleContexts do, and is it really necessary in my case? I prefer not to turn on language extensions willy-nilly without knowing whether I need them.
The function compiles fine if I leave off the type signature, but I prefer not to do that.

Haskell 98 doesn't allow constraints that looks like MonadError Failure m, they have to look like MonadError a m. The ability to have constraints like that was added to GHC however, which is what that extension does. I understand being wary of language extensions, but FlexibleContexts is pretty harmless.
I believe at the time Haskell 98 came out, the type theory to use constraints like that hadn't been developed, but since then it has. The extension turns on some extra code in the type checker which uses that theory. If you google around a little you might be able to find a paper on how it works.

Related

How to abstract over monads without fighting the type system in Haskell?

I'm currently building a server in haskell and as a newbie to the language, I'd like to try a new approach zu Monad composition. The idea is that we can write library methods like
isGetRequest :: (SupportsRequests m r) => m Bool
isGetRequest = do
method <- liftRequests $ requestMethod
return $ method == GET
class (Monad m, RequestSupport r) => SupportsRequests m r | m -> r where
liftRequests :: r a -> m a
class (Monad r) => RequestSupport r where
requestMethod :: r Method
which work without knowing the underlying monad. Of course in this example, it would have been sufficient to make isGetRequest operate directly on the (RequestSupport r) monad but the idea is that my library might also have more than one constraint on the monad. Yet, I do not want to implement all of those different concerns in the same module nor spread them across different modules (orphan instances!).
That's why the m monad only implements the Supports* classes, delegating the real concerns to other monads.
The above code should work perfectly (with some language extensions to GHC). Unfortunately, I got some problems with the CRUD (Create Read Update Delete) concern:
class (Monad m, CRUDSupport c a) => SupportsCRUD m c a | m a -> c where
liftCRUD :: c x -> m x
class (Monad c) => CRUDSupport c a | c -> a where
list :: c [a] -- List all entities of type a
No I get an error:
Could not deduce (SupportsCRUD m c a0) from the context [...]
The type variable 'a0' is ambiguous [...]
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the class method: liftCRUD [...]
Seems like the type checker doesn't like that the a parameter does not directly arise in the signature of liftCRUD. That's understandable because a cannot be derived from the functional dependencies.
The type checker in my brain tells me that it should not be a problem to infer the type a later on, using AllowAmbiguousTypes, when some method regarding CRUD is executed in a library method. Unfortunately, GHC seems unable to do this inference step, for example
bookAvailable :: (SupportsCRUD m c Book) => m Bool
bookAvailable = do
books <- liftCRUD (list :: c [Book]) -- I use ScopedTypeVariables
case books of
[] -> return False
_ -> return True
yields
Could not deduce (SupportsCRUD m c0 a1) arising from a use of 'liftCRUD' [...]
The type variables c0, a1 are ambiguous [...]
It seems that I am still unable to reason about the compiler. I there a way to resolve this problem? Or at least a way to understand what the compiler is able to infer?
Best Regards,
bloxx
To use ScopedTypeVariables you also need to bind the variables you want to be in scope with forall. So it should be
bookAvailable :: forall m c. (SupportsCRUD m c Book) => m Bool
...
That was all that was necessary (after some trivial fixes I made which I assume were typos from entering your question) for me to get the code to compile.

Unwrapping the STT monad in a transformer stack?

This question is apparently related to the problem discussed here and here. Unfortunately, my requirement is slightly different to those questions, and the answers given don't apply to me. I also don't really understand why runST fails to type check in these cases, which doesn't help.
My problem is this, I have one section of code that uses one monad stack, or rather a single monad:
import Control.Monad.Except
type KErr a = Except KindError a
Another section of code needs to integrate with this that wraps this within the STT monad:
type RunM s a = STT s (Except KindError) a
At the interface between these sections, I clearly need to wrap and unwrap the outer layer. I've got the following function to work in the KErr -> RunM direction:
kerrToRun :: KErr a -> RunM s a
kerrToRun e = either throwError return $ runExcept e
but for some reason I just can't get the converse to type check:
runToKErr :: RunM s a -> KErr a
runToKErr r = runST r
I'm working on the assumption that as the RunM's inner monad has the same structure as KErr, I can just return it once I've unwrapped the STT layer, but I don't seem to be able to get that far, as runST complains about its type arguments:
src/KindLang/Runtime/Eval.hs:18:21:
Couldn't match type ‘s’ with ‘s1’
‘s’ is a rigid type variable bound by
the type signature for runToKErr :: RunM s a -> KErr a
at src/KindLang/Runtime/Eval.hs:17:14
‘s1’ is a rigid type variable bound by
a type expected by the context:
STT s1 (ExceptT KindError Data.Functor.Identity.Identity) a
at src/KindLang/Runtime/Eval.hs:18:15
Expected type: STT
s1 (ExceptT KindError Data.Functor.Identity.Identity) a
Actual type: RunM s a
I've also tried:
runToKErr r = either throwError return $ runExcept $ runST r
in order to more strongly isolate runST from its expected return type, in case that was the cause of the issue, but the results are the same.
Where is this s1 type coming from, and how do I persuade ghc that it's the same type as s?
(The below talks about ST s a but applies just the same as STT s m a; I've just avoided the unnecessary complication of talking about the transformer version below)
The problem you are seeing is that runST has type (forall s. ST s a) -> a to isolate any potential (STRef-changing) effects of the computation from the outside, pure world. The whole point of the s phantom type that all ST computations, STRefs, etc. are tagged with, is to track which "ST-domain" they belong to; and the type of runST ensures that nothing can pass between domains.
You can write runToKErr by enforcing the same invariant:
{-# language Rank2Types #-}
runToKErr :: (forall s. RunM s a) -> KErr a
runToKErr = runST
(of course, you might realize further down the road that this restriction is too strong for the program you hope to write; at that point you'll need to lose hope, sorry, I mean you'll need to redesign your program.)
As for the error message, the reason you can't "convince the type checker that s1 and s are the same type" is because if I pass you an ST s a for a given choice of s and a, that is not the same as giving you something which allows you to choose your own s. GHC chose s1 (a Skolemized variable) as s and so tries to unify ST s a with ST s1 a

GHC TypeLits without values

Trying to design a type-driven API, I've been trying to get something like the following working (using much more complicated code/attempts, this is stripped down to the minimum required to clarify what I'm looking for):
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
module Main where
import Data.Proxy
import GHC.TypeLits
type Printer (s :: Symbol) = IO ()
concrete :: Printer "foo"
concrete = generic
generic :: KnownSymbol s => Printer s
generic = putStrLn (symbolVal (Proxy :: Proxy s))
main :: IO ()
main = concrete
This program would print 'foo', but doesn't:
Could not deduce (KnownSymbol s0)
arising from the ambiguity check for ‘generic’
from the context (KnownSymbol s)
bound by the type signature for
generic :: KnownSymbol s => Printer s
at test5.hs:14:12-37
The type variable ‘s0’ is ambiguous
In the ambiguity check for:
forall (s :: Symbol). KnownSymbol s => Printer s
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature for ‘generic’:
generic :: KnownSymbol s => Printer s
Enabling AllowAmbiguousTypes doesn't really help. Any way to get this working anyway?
Type synonyms (defined with type) are replaced with their definition during typechecking. The problem is that Printer has no reference to s in its definition, which leads to the following constraint:
generic :: KnonwSymbol s => IO ()
This type signature does not have an s right of the => and so fails the ambiguity check. It can't really work because there's nowhere to specify what s should be when you use it.
Unfortunately, GHC is inconsistent about how it represents type synonyms in error messages. Sometimes they are expanded and sometimes they are preserved. Ironically, I think improvements in the error messages have made this particular error harder to track down: normally, expressing the error in terms of the types you defined is clearer, but here it hides the cause of the ambiguity.
What you need is some way to supply the relevant type-level symbol that does not rely on type synonyms. But first, you need to enable ScopedTypeVariables and add a forall to the signature of generic to make sure the s in the type signature and the s in Proxy :: Proxy s are the same.
There are two possibilities:
change Printer to a newtype and unwrap it when you use it:
newtype Printer (s :: Symbol) = Printer { runPrinter :: IO () }
generic :: forall s. KnownSymbol s => Printer s
generic = Printer $ putStrLn (symbolVal (Proxy :: Proxy s))
main = runPrinter generic
pass in an extra Proxy argument to generic, just like symbolVal:
concrete :: Printer "foo"
concrete = generic (Proxy :: Proxy "foo")
generic :: forall proxy s. KnownSymbol s => proxy s -> IO ()
generic _ = putStrLn (symbolVal (Proxy :: Proxy s))
Having proxy as a type variable is a neat idiom that lets you not depend on Data.Proxy and lets callers pass in whatever they want in its stead.
This is wrong:
generic :: KnownSymbol s => Printer s
generic = ...(Proxy :: Proxy s)
The last s has nothing to do with the s above it. It is locally implicitly universally quantified, as in top-level type annotations. The code actually means
generic :: KnownSymbol s => Printer s
generic = ...(Proxy :: forall z. Proxy z)
To fix the above, enable ScopedTypeVariables and use
-- the explicit forall makes s available below
generic :: forall s. KnownSymbol s => Printer s
generic = ...(Proxy :: Proxy s)
There are other issues, though, as Tikhon Jelvis points out in his answer.

Use of Error typeclass

What is the use of Error typeclass:
class Error a where
noMsg :: a
strMsg :: String -> a
There is also another typeclass named MonadError which makes sense in monadic computation. But where is Error used ? I haven't seen the usage of noMsg and strMsg yet anywhere.
For historical reasons, the Monad m typeclass includes fail :: String -> m a. For Either e to implement such a method, we must have a way to turn a String into an e; the Error typeclass was invented to allow this via strMsg. The addition of noMsg is an additional convenience.

Type Constraints in Typeclass

For fun I'm building a parser library. In this library I have a Parser data type:
data Parser e a = Parser (String -> Either e (a, String))
I'm able to define Functor and Applicative instances of Parser, but I don't think I can make an Alternative instance without constraining the "error" type or the "value" type the parser could return. Originally, this made me create an Applicative instance for when the error types are String messages, but I realized that I should be able to release this constraint to any message data type that has an Alternative (or maybe Monoid instead?) instance as well. With that in mind I wrote this:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
instance Alternative e => Alternative (Parser e)
where
empty = Parser $ \s -> Left empty
(<|>) (Parser p1) (Parser p2) = Parser $ \s -> tryParser s p2 $ p1 s
where
tryParser s p2 (Left _ ) = p2 s
tryParser _ _ x = x
Unfortunately, this fails to compile. When I load it into ghci I get this error message:
Parsertest.hs:31:47:
Expecting one more argument to `e'
In the instance declaration for `Alternative (Parser e)'
Failed, modules loaded: none.
When I search online, this seems to be the solution, but it doesn't work for me. What am I missing?
The problem is that Alternative is for type constructors of kind * -> *, so if you say
instance Alternative e => ....
then e has to be a type constructor, not a type. So e could be [] or Maybe or something, but not Int.
Alternative's operator is <|> which has type Alternative e => e a -> e a -> e a. This forces e to take an argument to make a type, like Maybe has to take an argument, eg Maybe Int.
Use Monoid instead of Alternative, because it's a type class instead of a constructor class. It's operator mappend has type Monoid e => e -> e -> e which is what you want for combining errors.

Resources