Why does these instances not produce the Overlapping Instances error - haskell

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.

Related

GHC stuck due to UndecidableSuperClasses - expected behaviour or bug?

The following snippet makes GHC (checked with 8.6.2 & 8.4.4) stuck during compilation:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
import GHC.Exts (Constraint)
data T = T
type family F t (c :: * -> Constraint) :: Constraint
type instance F T c = c T
class F t C => C t where
t :: C T => t
t = undefined
I think that it gets stuck because for t GHC tries to find C T, which leads to F T C which expands via type family F back to C T, which is what it was looking for (infinite loop).
I suppose that theoretically GHC could tell that it reached its quest for C T from itself and that anything that depends on itself can work fine recursively, or am I misunderstanding something?
Side note: in the real example where I stumbled upon this behaviour I was able to achieve what I wanted without the compiler being stuck by replacing UndecidableSuperClasses with Data.Constraint.Dict instead.
UndecidableSuperClasses does not make instance resolution lazy. The compiler will still expand superclass constraints as far as possible. I believe that the fields in instance dictionaries that point to the superclass dictionaries are strict, and GHC actually pins them down at compile time. This is in contrast to UndecidableInstances, which allows instance constraints to be treated (a bit) lazily.
deriving instance Show (f (Fix f)) => Show (Fix f)
will work just fine. When resolving an instance for, e.g., Show (Fix Maybe)), GHC will see that it needs Show (Maybe (Fix Maybe)). It then sees it needs Show (Fix Maybe) (which it's currently resolving) and accept that thanks to UndecidableInstances.
All UndecidableSuperClases does is disable the checks that guarantee that expansion won't loop. See the bit near the beginning of Ed Kmett's talk where he describes the process "reaching a fixed point".
Consider a working example (ripped from Data.Constraint.Forall):
type family Skolem (p :: k -> Constraint) :: k
class p (Skolem p) => Forall (p :: k -> Constraint)
GHC only accepts this with UndecidableSuperclasses. Why? Because it doesn't know anything about what that constraint might mean. As far as it knows, it could be the case that p (Skolem p) will reduce to Forall p. And that could actually happen!
class Forall P => P x
-- This definition loops the type checker
foo :: P x => x
foo = undefined

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

Is there a way to show "showable" stuff [duplicate]

Suppose I have a simple data type in Haskell for storing a value:
data V a = V a
I want to make V an instance of Show, regardless of a's type. If a is an instance of Show, then show (V a) should return show a otherwise an error message should be returned. Or in Pseudo-Haskell:
instance Show (V a) where
show (V a) = if a instanceof Show
then show a
else "Some Error."
How could this behaviour be implemented in Haskell?
As I said in a comment, the runtime objects allocated in memory don't have type tags in a Haskell program. There is therefore no universal instanceof operation like in, say, Java.
It's also important to consider the implications of the following. In Haskell, to a first approximation (i.e., ignoring some fancy stuff that beginners shouldn't tackle too soon), all runtime function calls are monomorphic. I.e., the compiler knows, directly or indirectly, the monomorphic (non-generic) type of every function call in an executable program. Even though your V type's show function has a generic type:
-- Specialized to `V a`
show :: V a -> String -- generic; has variable `a`
...you can't actually write a program that calls the function at runtime without, directly or indirectly, telling the compiler exactly what type a will be in every single call. So for example:
-- Here you tell it directly that `a := Int`
example1 = show (V (1 :: Int))
-- Here you're not saying which type `a` is, but this just "puts off"
-- the decision—for `example2` to be called, *something* in the call
-- graph will have to pick a monomorphic type for `a`.
example2 :: a -> String
example2 x = show (V x) ++ example1
Seen in this light, hopefully you can spot the problem with what you're asking:
instance Show (V a) where
show (V a) = if a instanceof Show
then show a
else "Some Error."
Basically, since the type for the a parameter will be known at compilation time for any actual call to your show function, there's no point to testing for this type at runtime—you can test for it at compilation time! Once you grasp this, you're led to Will Sewell's suggestion:
-- No call to `show (V x)` will compile unless `x` is of a `Show` type.
instance Show a => Show (V a) where ...
EDIT: A more constructive answer perhaps might be this: your V type needs to be a tagged union of multiple cases. This does require using the GADTs extension:
{-# LANGUAGE GADTs #-}
-- This definition requires `GADTs`. It has two constructors:
data V a where
-- The `Showable` constructor can only be used with `Show` types.
Showable :: Show a => a -> V a
-- The `Unshowable` constructor can be used with any type.
Unshowable :: a -> V a
instance Show (V a) where
show (Showable a) = show a
show (Unshowable a) = "Some Error."
But this isn't a runtime check of whether a type is a Show instance—your code is responsible for knowing at compilation time where the Showable constructor is to be used.
You can with this library: https://github.com/mikeizbicki/ifcxt. Being able to call show on a value that may or may not have a Show instance is one of the first examples it gives. This is how you could adapt that for V a:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
import IfCxt
import Data.Typeable
mkIfCxtInstances ''Show
data V a = V a
instance forall a. IfCxt (Show a) => Show (V a) where
show (V a) = ifCxt (Proxy::Proxy (Show a))
(show a)
"<<unshowable>>"
This is the essence of this library:
class IfCxt cxt where
ifCxt :: proxy cxt -> (cxt => a) -> a -> a
instance {-# OVERLAPPABLE #-} IfCxt cxt where ifCxt _ t f = f
I don't fully understand it, but this is how I think it works:
It doesn't violate the "open world" assumption any more than
instance {-# OVERLAPPABLE #-} Show a where
show _ = "<<unshowable>>"
does. The approach is actually pretty similar to that: adding a default case to fall back on for all types that do not have an instance in scope. However, it adds some indirection to not make a mess of the existing instances (and to allow different functions to specify different defaults). IfCxt works as a a "meta-class", a class on constraints, that indicates whether those instances exist, with a default case that indicates "false.":
instance {-# OVERLAPPABLE #-} IfCxt cxt where ifCxt _ t f = f
It uses TemplateHaskell to generate a long list of instances for that class:
instance {-# OVERLAPS #-} IfCxt (Show Int) where ifCxt _ t f = t
instance {-# OVERLAPS #-} IfCxt (Show Char) where ifCxt _ t f = t
which also implies that any instances that were not in scope when mkIfCxtInstances was called will be considered non-existing.
The proxy cxt argument is used to pass a Constraint to the function, the (cxt => a) argument (I had no idea RankNTypes allowed that) is an argument that can use the constraint cxt, but as long as that argument is unused, the constraint doesn't need to be solved. This is similar to:
f :: (Show (a -> a) => a) -> a -> a
f _ x = x
The proxy argument supplies the constraint, then the IfCxt constraint is solved to either the t or f argument, if it's t then there is some IfCxt instance where this constraint is supplied which means it can be solved directly, if it's f then the constraint is never demanded so it gets dropped.
This solution is imperfect (as new modules can define new Show instances which won't work unless it also calls mkIfCxtInstances), but being able to do that would violate the open world assumption.
Even if you could do this, it would be a bad design. I would recommend adding a Show constraint to a:
instance Show a => Show (V a) where ...
If you want to store members in a container data type that are not an instance of Show, then you should create a new data type fore them.

Using constraint kinds and type families with 'limited' constraints

I'm working on an applicative functor that contains a monoid to "view" the execution. However, sometimes I don't care about this part at all, so the choice of monoid is irrelevant as it will never be consumed. I've simplified what I have into:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a () where render = const ()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render is used to transform various as into a single b. Merge is a big simplification of my actual functor, but the point is it contains a type family/constraint and my intention of that is to specify exactly what Renderers a Merge requires.
Now, I might want to "run" the Merge, but discard the view, which is akin to something like:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of () -> 5
But this will fail because:
Could not deduce (Renderer a ()) arising from a use of merge
I chose () as my monoid because forall a, we have an instance of Render a (). So if there was a way to say that Merge a just means a collection Render constraints then this would work fine. Of course, Merge a is more general than that - it could add arbitrary constraints, which explains the compilation error.
Is there anyway to achieve what I want without changing the signature of runFoo?
This might not scale if you have a lot of these cases, but this works:
class Renderer a () => Merge a where
...

Implementation of "show" for function

I would like to implement the show method for (binary) functions and make it able to distingish endofunctions (a -> a).
Something like the pseudo-haskell code:
instance Show (a->b) where
show fun = "<<Endofunction>>" if a==b
show fun = "<<Function>>" if a\=b
How can I distinguish the two cases?
You need to enable some extensions:
{-# LANGUAGE OverlappingInstances, FlexibleInstances #-}
module FunShow where
instance Show ((->) a a) where
show _ = "<<Endofunction>>"
instance Show ((->) a b) where
show _ = "<<Function>>"
You need OverlappingInstances since the instance a -> b also matches endofunctions, so there's overlap, and you need FlexibleInstances because the language standard mandates that the type variables in instance declarations are distinct.
*FunShow> show not
"<<Endofunction>>"
*FunShow> show fst
"<<Function>>"
*FunShow> show id
"<<Endofunction>>"

Resources