Last active
May 19, 2018 18:16
-
-
Save kcsongor/e0e9b84fa334ff2e31b12951312224f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE RankNTypes, TypeApplications, TypeInType, TypeOperators, | |
ScopedTypeVariables, TypeFamilies, UndecidableInstances, | |
GADTs, ConstraintKinds, AllowAmbiguousTypes #-} | |
module Elem where | |
import Data.Type.Equality | |
import Data.Kind | |
import Unsafe.Coerce | |
data Dict c where | |
Dict :: c => Dict c | |
class Elem x xs | |
instance Elem x (x ': ys) | |
instance {-# INCOHERENT #-} Elem x xs => Elem x (y ': xs) | |
-- * The first instance matches only when `x ~ y`. If don't want to forego | |
-- parametricity, we can't inspect this. | |
-- | |
-- * The second instance _always_ matches, which means that no matter what `y` | |
-- gets instantiated to, the resulting constructor will always be `There`. Since | |
-- resolving the instances depends on the instantiation of `x` and `y`, we need | |
-- an INCOHERENT pragma to tell GHC that we really are happy with the second one. | |
elemThere :: forall x xs y. Dict (Elem x xs) -> Dict (Elem x (y : xs)) | |
elemThere Dict = Dict |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment