Skip to content

Instantly share code, notes, and snippets.

@kcsongor
Last active May 19, 2018 18:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kcsongor/e0e9b84fa334ff2e31b12951312224f5 to your computer and use it in GitHub Desktop.
Save kcsongor/e0e9b84fa334ff2e31b12951312224f5 to your computer and use it in GitHub Desktop.
{-# 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