packages feed

prob-fx-0.1.0.2: src/FindElem.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{- | Auxiliary definitions for finding a type in a type-level list.
-}

module FindElem (
    FindElem(..)
  , Idx(..)) where

import GHC.TypeLits ( TypeError, ErrorMessage(Text, (:<>:), (:$$:), ShowType) )

-- | Proof that @x@ is an element of the type-level list @xs@
class FindElem x xs where
  findElem :: Idx x xs

-- | The integer index of @x@ in @xs@
newtype Idx x xs = Idx {unIdx :: Int}

instance FindElem x (x ': xs) where
  findElem = Idx 0

instance {-# OVERLAPPABLE #-} FindElem x xs => FindElem x (x' : xs) where
  findElem = Idx $ 1 + unIdx (findElem :: Idx x xs)

instance TypeError ('Text "Cannot unify effect types." ':$$:
                    'Text "Unhandled effect: " ':<>: 'ShowType x ':$$:
                    'Text "Perhaps check the type of effectful computation and the sequence of handlers for concordance?")
  => FindElem x '[] where
  findElem = error "unreachable"