Why does this function that uses a scoped type variable in a where clause not typecheck? - haskell

I have a function that has a value defined in a where clause, and I want to give it an explicit type annotation. The annotation needs to use a type variable from the top-level function, so it was my understanding that I needed to use ScopedTypeVariables. Here is a minimal reduction of the problem:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad.Trans.Except
import Data.Functor.Identity
f :: ExceptT String Identity a -> Maybe a
f m = Nothing
where x :: Identity (Either String a)
x = runExceptT m
This code does not typecheck. It fails with the following error message:
Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for f :: ExceptT String Identity a -> Maybe a
at src/Lib.hs:20:6
‘a1’ is a rigid type variable bound by
the type signature for x :: Identity (Either String a1)
at src/Lib.hs:22:14
Expected type: ExceptT String Identity a1
Actual type: ExceptT String Identity a
Relevant bindings include
x :: Identity (Either String a1) (bound at src/Lib.hs:23:9)
m :: ExceptT String Identity a (bound at src/Lib.hs:21:3)
f :: ExceptT String Identity a -> Maybe a
(bound at src/Lib.hs:21:1)
In the first argument of ‘runExceptT’, namely ‘m’
In the expression: runExceptT m
Why does this fail? I do not understand why this would cause problems—it seems like a textbook use of scoped type variables. For reference, I am using GHC 7.10.3.

You need an explicit forall:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad.Trans.Except
import Data.Functor.Identity
f :: forall a. ExceptT String Identity a -> Maybe a
f m = Nothing
where x :: Identity (Either String a)
x = runExceptT m
but why
That is a great question. This appears to be a rule of ScopedTypeVariables. We know in GHC Haskell that all top-level variables are implicitly forall'd, as documented here. One would suspect that the GHC devs added this behavior for backwards compatibility: without this rule, a file without the extension turned on could stop type-checking once the extension was turned on. We can easily imagine a scenario where helper functions declared in the where block to inadvertently reuse the common type variable names a, b, c, t, so on. It would be great if someone could find the exact spot in the GHC source code where this distinction between explicit and implicit forall'd variables arose.
update
Here we go (although this is all guesswork from the comments and grepping):
While type-checking user signatures, the function tcUserTypeSig invokes findScopedTyVars. TcBinds.hs:ef44606:L1786
findScopedTyVars in TcRnTypes filters for foralls by calling tcSplitForAllTys. TcRnTypes.hs:ef44606:L1221
Which is a wrapper around splitForAllTys, which folds over a type's subtypes to build up a list of type variables introduced by foralls. Types/Type.hs:ef44606:L1361

Related

Using a default implementation of typeclass method to omit an argument

I want to be able to define a (mulit-parameter-) typeclass instance whose implementation of the class's method ignores one of its arguments. This can be easily done as follows.
instance MyType MyData () where
specific _ a = f a
As I'm using this pattern in several places, I tried to generalize it by adding a specialized class method and adequate default implementations. I came up with the following.
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
class MyType a b where
specific :: b -> a -> a
specific = const dontCare
dontCare :: a -> a
dontCare = specific (undefined :: b)
{-# MINIMAL specific | dontCare #-}
This however yields the error Could not deduce (MyType a b0) arising from a use of ‘dontCare’ [..] The type variable ‘b0’ is ambiguous. I don't see why the latter should be the case with the type variable b being scoped from the class signature to the method declaration. Can you help me understand the exact problem that arises here?
Is there another reasonable way to achieve what I intended, namely to allow such trimmed instances in a generic way?
The problem is in the default definition of specific. Let's zoom out for a second and see what types your methods are actually given, based on your type signatures.
specific :: forall a b. MyType a b => b -> a -> a
dontCare :: forall a b. MyType a b => a -> a
In the default definition of specific, you use dontCare at type a -> a. So GHC infers that the first type argument to dontCare is a. But nothing constrains its second type argument, so GHC has no way to select the correct instance dictionary to use for it. This is why you ended up needing AllowAmbiguousTypes to get GHC to accept your type signature for dontCare. The reason these "ambiguous" types are useful in modern GHC is that we have TypeApplications to allow us to fix them. This definition works just fine:
class MyType a b where
specific :: b -> a -> a
specific = const (dontCare #_ #b)
dontCare :: a -> a
dontCare = specific (undefined :: b)
{-# MINIMAL specific | dontCare #-}
The type application specifies that the second argument is b. You could fill in a for the first argument, but GHC can actually figure that one out just fine.

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

Type inference in haskell and Arrows

I'm trying to use arrows and faced annoying problem - I have to provide explicit types for all functions I implemented.
If I not provide it ghc outputs some error like
No instance for (Arrow a0) arising from a use of ‘...’
The type variable ‘a0’ is ambiguous
I can provide explicit types but it's VERY annoying, as every time I change some function it's a possibility that I have to manually alter types of every function depended on changed.
Is it possible to force ghc to infer function types automatically?
Trivial case
import Control.Arrow
ss = arr
causes
No instance for (Arrow a0) arising from a use of ‘arr’
The type variable ‘a0’ is ambiguous
Relevant bindings include
ss :: (b -> c) -> a0 b c (bound at src/Main.hs:62:1)
Note: there are several potential instances:
instance Arrow Coroutine -- Defined at src/Main.hs:33:10
instance Arrow (->) -- Defined in ‘Control.Arrow’
instance Monad m => Arrow (Kleisli m) -- Defined in ‘Control.Arrow’
In the expression: arr
In an equation for ‘ss’: ss = arr
while code with exactly the same semantic
import Control.Arrow
ss :: forall a b c. (Arrow a) => (b -> c) -> a b c
ss = arr
compiles pretty well.
Easiest thing is to turn off the monomorphism restriction - put this at the top of your source file:
{-# LANGUAGE NoMonomorphismRestriction #-}
The reason for your error is that although Haskell can infer the type for ss fine, the monomorphism restriction requires that in a top-level definitions of a value, the type is not polymorphic over a type-class (e.g. Arrow) unless there is an explicit type signature.

How do I specify a type variable used in an inline type, is the same as a type variable used in a function definition?

(Apologies if my terminology is wrong).
I'm trying to write a wrapper function that handles exceptions: if the given IO action throws, it returns Nothing (inside an IO context of course), but if the given IO action succeeds, it returns Just v.
tryMaybe :: IO a -> IO (Maybe a)
tryMaybe action = do
result <- (try action) :: IO (Either SomeException a)
return $ case result of
Left _ -> Nothing
Right v -> Just v
This results in the compiler error message:
Couldn't match type `a' with `a1'
`a' is a rigid type variable bound by
the type signature for tryMaybe :: IO a -> IO (Maybe a)
at src/Database.hs:33:13
`a1' is a rigid type variable bound by
an expression type signature: IO (Either SomeException a1)
at src/Database.hs:35:15
Expected type: IO a1
Actual type: IO a
In the first argument of `try', namely `action'
I'm guessing that the type variable a in the first line isn't the same as the a in the third line - they just happen to have the same name in the source code, and the compiler has renamed it a1 in the error message.
So how do I tell Haskell that these are the same types?
You need to enable the ScopedTypeVariables extension, and the change the type signature of the top-level function to start with forall a .:
{-# LANGUAGE ScopedTypeVariables #-}
...
tryMaybe :: forall a . IO a -> IO (Maybe a)
...
The forall syntax brings the type variable a into scope for the entire body of tryMaybe, rather than it being limited to the type signature which is the default. This is mainly a historical anomaly rather than a deliberate design.

Trouble explicitly specifying a type using a type variable [duplicate]

This question already has answers here:
How to reuse a type variable in an inner type declaration
(4 answers)
Arrays with rigid variable
(2 answers)
Closed 8 years ago.
The following is a simplified example of what I'm trying to do...
test :: Bounded a => Maybe a -> a
test (Just x) = x
test Nothing = (maxBound :: a)
The maxBound function is polymorphic - one of the methods of the Bounded typeclass. Because of that, when I use it I need to specify which version of Bounded I want. In this simplified example, that type could be inferred from the context - but in the real problem it can't - the explicit type is necessary in the real problem, though not really here.
My function is polymorphic too. I can't specify a concrete type directly, only a type variable. The appropriate type variable is a, for which I have specified the Bounded a constraint.
Compiling this, I get the following error...
temp.hs:4:18:
Could not deduce (Bounded a1) arising from a use of `maxBound'
from the context (Bounded a)
bound by the type signature for test :: Bounded a => Maybe a -> a
at temp.hs:2:9-33
Possible fix:
add (Bounded a1) to the context of
an expression type signature: a1
or the type signature for test :: Bounded a => Maybe a -> a
In the expression: (maxBound :: a)
In an equation for `test': test Nothing = (maxBound :: a)
As far as I can tell, this means that the a in maxBound :: a was considered separate from the a that I intended (the type variable in the signature for the function). a1 is the new name that GHC invented to disambiguate the two a variables which it considers separate. GHC considers the a in maxBound :: a to indicate that it can use any type here (!) and therefore complains because "any type" isn't restrictive enough.
This is using GHC version 7.6.3 as supplied in the (I think) most recent Haskell Platform.
I've had similar issues before, but always mixed with other issues, so the problem went away once I fixed those other problems. I dismissed it as being caused by the other issues and forgot about it. No such luxury here - that minimal example above isn't the real problem, but it depends on a solution to the exact same problem.
So... why is GHC treating the a in maxBound :: a as independent of the type variable a for the whole function? And how do I fix this to select the correct version of maxBound?
Main problem is in fact, that GHC tried to see function as
test :: forall a. Bounded a => Maybe a -> a
test (Just x) = x
test Nothing = (maxBound :: forall a. a)
You need ScopedTypeVariables extension and rewrite function to:
{-# LANGUAGE ScopedTypeVariables #-}
test :: forall a. Bounded a => Maybe a -> a
test (Just x) = x
test Nothing = (maxBound :: a)
Now we see, that inner a is depend on outer a
UPDATE
If you already wrote the signatiure, you don't need any extension.
Next function works fine!
test :: Bounded a => Maybe a -> a
test (Just x) = x
test Nothing = maxBound

Resources