Why does GHC think that the type variable is ambiguous for a class with a default implementation? - haskell

In the following example I would expect GHC to be able to constrain the variable a to type A because that's what I say in instance EAmbiguous A. However when loading this into ghci I get:
Ambiguous type variable ‘a0’ arising from a use of ‘Main.$dmcount’
The code in question:
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
import GHC.Generics (Rep, Generic)
import GHC.Base (Type)
class EAmbiguous a where
count :: Int
default count :: (Generic a, GenericAmbiguous (Rep a)) => Int
count = genericCount #(Rep a)
class GenericAmbiguous (a :: Type -> Type) where
genericCount :: Int
instance GenericAmbiguous (f p) where
genericCount = 10
data A = A deriving Generic
-- The error happens when defining a body-less instance:
-- • Ambiguous type variable ‘a0’ arising from a use of ‘Main.$dmcount’
-- prevents the constraint ‘(Generic a0)’ from being solved.
instance EAmbiguous A
I've been looking at this for a good while and I'm convinced that this should work, but I'm clearly missing something. So my question is: Why can't GHC solve a to A?

This turned out to be a GHC bug which is fixed in GHC 8.0.2: https://ghc.haskell.org/trac/ghc/ticket/12220

Related

Elimination by `TypeError` constraint

I'd like to use a TypeError constraint to make a "non-instance" produce a more meaningful type error:
{-# LANGUAGE DataKinds, KindSignatures #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
import GHC.TypeLits
import Data.Proxy
class Compat (x :: Bool) (y :: Bool) where
combine :: Proxy x -> Proxy y -> Int
instance Compat False pre2 where
combine _ _ = 42
instance Compat True False where
combine _ _ = 1
instance (TypeError (Text "Meaningful error message goes here")) => Compat True True where
combine = _
At the hole, I'd like to fill it using elimination by the TypeError constraint, i.e. use the fact that I have a TypeError constraint in scope to avoid having to write undefined or error or similar.
Is that possible?
I don't think this is possible with the standard TypeError, but you can define your own variant (TE below) so to provide the eliminator you need.
{-# LANGUAGE
DataKinds, UndecidableInstances,
MultiParamTypeClasses, KindSignatures, TypeFamilies #-}
import GHC.TypeLits
import Data.Kind
class Impossible where
impossible :: a
type family TE (t :: ErrorMessage) :: Constraint where
TE t = (TypeError t, Impossible)
class C t where
foo :: t -> Bool
instance (TE (Text "impossible")) => C Bool where
foo _ = impossible

Why can I not use type variables in this instance declaration?

I'm trying to use TypeApplications to disambiguate between which instance of a type class I am calling. Unfortunately, it seems that an instance declaration's type parameters cannot be used in the instance body. Specifically, in this toy example:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
class Foo a where
foo :: String
instance Foo () where
foo = "()"
instance Foo Int where
foo = "Int"
class Bar b where
bar :: String
instance Foo a => Bar a where
bar = foo #a
will error with Not in scope: type variable 'a' at the last line. If I remove the type application, instead the error Could not deduce (Foo a0) from the context Foo a is given, which is reasonable, ass foo by itself is ambiguous.
Is there some way for me to access the type parameter, or otherwise coerce the compiler into recognising this?
A type variable can be used in an instance declaration, but only if it's scoped:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE TypeApplications, AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax #-}
class Foo a where foo :: String
class Bar b where bar :: String
instance ∀ a . Foo a => Bar a where
bar = foo #a
As always, ∀ can also be written forall if you prefer ASCII.

How to safely case on kind-constrained type variable in Haskell?

Question
I want to case on a type variable that is restricted to finitely many possibilities due to a kind constraint. And I want to know statically that casing will always discover one of these finitely many possibilities. I can't figure out how to write this case without an unreachable catch-all.
As a concrete example, suppose I have a data kind
data{-kind-} Temp = Hot | Cold
Then my goal is write a function like caseTemp below that determines the Temp a given Temp-kinded type. Something like
data CaseTemp (t :: Temp) where
IsHot :: CaseTemp 'Hot
IsCold :: CaseTemp 'Cold
caseTemp :: forall (t :: Temp). CaseTemp t
caseTemp = ???
I'm OK with having some extra constraints on caseTemp, like the Typeable t in my failed attempt below. Or even with an entirely different approach.
Failed Solution Attempt
Here is my best attempt, but it includes a branch that I think should be unreachable, and that would allow caseTemp to break silently if I added another constructor to Temp (tested in GHC 8.0.2):
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE StandaloneDeriving #-}
module SOQuestion where
import Data.Typeable ( (:~:)(..), Typeable, eqT )
data{-kind-} Temp = Hot | Cold
data CaseTemp (t :: Temp) where
IsHot :: CaseTemp 'Hot
IsCold :: CaseTemp 'Cold
deriving instance Show (CaseTemp t)
caseTemp :: forall (t :: Temp). Typeable t => CaseTemp t
caseTemp =
case eqT :: Maybe (t :~: 'Hot) of
Just Refl -> IsHot
Nothing -> case eqT :: Maybe (t :~: 'Cold) of
-- (GHC says this "pattern match is redundant" ???
-- Sounds like a bug!)
Just Refl -> IsCold
-- MY QUESTION: is there a way to eliminate the
-- unreachable branch here?
Nothing -> error "Unreachable!"
The problem with this attempt is that GHC believes the Nothing -> error "Unreachable!" branch is reachable.
Updates
User #Alec mentions that Any :: Temp is a fundamental reason that it's impossible to do what I want, since e.g.
import GHC.Prim ( Any )
[...]
badCase :: CaseTemp Any
badCase = undefined :: CaseTemp Any
is accepted by GHC. However, Any is not Typeable, so it's not clear to me that putting constraints on caseTemp couldn't work around this.
There isn't a direct way, because when eqT returns Nothing it doesn't come with a disequality proof.
How about using a type class?
class IsTemp (b :: Temp) where
caseTemp :: CaseTemp b

Haskell Constraint Kinds - default constraint for default implementation

Headline: I would like to provide a default implementation for a class method parametrised over a constraint, which uses the default instance for that constraint.
Consider the following:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts (Constraint)
class Foo a where
type Ctx a :: Constraint
type Ctx a = Show a
foo :: (Ctx a) => a -> String
foo = show
main :: IO ()
main = putStrLn "Compiles!"
This fails to compile with the error of:
Could not deduce (Show a) arising from a use of ‘show’
from the context (Foo a)
From my perspective, it should be using the default constraint of Show, which would let this compile. Is there any reason this doesn't work, or can anyone suggest a good way to achieve this?
You can achieve this using DefaultSignatures:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DefaultSignatures #-}
import GHC.Exts (Constraint)
class Foo a where
type Ctx a :: Constraint
type Ctx a = Show a
foo :: (Ctx a) => a -> String
default foo :: Show a => a -> String
foo = show
main :: IO ()
main = putStrLn "Compiles!"
From my perspective, it should be using the default constraint of Show, which would let this compile.
The reason your approach doesn't work is that the user of your class should be able to override any number of defaults. Your code would break if someone tried to override Ctx but not foo.

Why does these instances not produce the Overlapping Instances error

Let's define a collapse function that collapses any possibly nested Maybe (Maybe (... a)...) to Maybe a:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoOverlappingInstances #-}
{-# LANGUAGE TypeFamilies #-}
module MaybeCollapsable where
class M a b where
collapse :: Maybe a -> Maybe b
instance (a ~ b) => M a b where
collapse = id
instance M a b => M (Maybe a) b where
collapse Nothing = Nothing
collapse (Just a) = collapse a
It works well
> collapse (Just (Just (Just 1)))
Just 1
Although, it is strange. Both instances seems to be matchable for that particular case (a ~ Maybe x and b ~ Maybe x) but compiler produce no Overlapping Instances error.
How it works with -XNoOverlappingInstances?
And, by the way, is it a safe and usable way to define such method for collapsing nested Maybe?
I think the problem might be that IncoherentInstances is overriding the NoOverlappingInstances directive. If you remove IncoherentInstances the code gives an overlapping instances error. The GHC manual is not clear on this ( http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/type-class-extensions.html#instance-overlap ) but the two flags do clearly relate.
If you turn off IncoherentInstances and turn on OverlappingInstances your code works fine. So drop the IncoherentInstances flag, and I think the behaviour will be as you initially expected: the overlapping instances flag makes the different between working and not working.

Resources