Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a constraint of Maybe a where Eq a

Tags:

haskell

How can I constrain to Maybe a where Eq a? It needs to be of kind * -> Constraint

What I tried:

class (a ~ Maybe b, Eq b) => K a where
instance (a ~ Maybe b, Eq b) => K a where

Error:

Not in scope: type variable ‘b’

Example Usage:

data Test c = forall a. (c a) => Test a
r :: Test K -> Maybe Bool
r (Test o) = (==) <$> o <*> o -- I need GHC to infer that o is Maybe Eq

Cases that work:

pp :: Test ((~) String) -> String
pp (Test o) = o ++ "X" -- GHC infers that o is a string

hh :: Test Eq -> Bool
hh (Test o) = o == o -- GHC infers that o is Eq

Generic answer here: Is there a general way to apply constraints to a type application?

like image 885
michaelmesser Avatar asked Dec 13 '16 00:12

michaelmesser


2 Answers

The following compiles on my machine. No idea how sensible it is.

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ConstraintKinds #-}
class (Eq (UnMaybe a), a ~ Maybe (UnMaybe a)) => EqMaybe a where
    type UnMaybe a

instance Eq a => EqMaybe (Maybe a) where
    type UnMaybe (Maybe a) = a

data Test c = forall a. c a => Test a
r :: Test EqMaybe -> Maybe Bool
r (Test o) = (==) <$> o <*> o
f :: Test Eq -> Test EqMaybe
f (Test o) = Test (Just o)
like image 156
Daniel Wagner Avatar answered Oct 09 '22 12:10

Daniel Wagner


This is a known issue. GHC is choking up because you have introduced a new type variable b not mentioned anywhere else in the instance head. One workaround is to use type families and constraint kinds.

{-# LANGUAGE ConstraintKinds, TypeFamilies, UndecideableInstances, 
             UndecideableSuperclasses, FlexibleInstances
  #-}

import GHC.Exts (Constraint)
import GHC.Prim (Any)

type family MaybeEq x :: Constraint where
  MaybeEq (Maybe a) = Eq a
  MaybeEq _         = Any    -- A good "unsatisfiable" constraint

class MaybeEq a => K a where
instance MaybeEq a => K a where
like image 30
Alec Avatar answered Oct 09 '22 14:10

Alec