Created
November 12, 2020 05:44
-
-
Save ajnsit/3945709347c95ce8c8a3ad950ddec116 to your computer and use it in GitHub Desktop.
An example of an equality class that works across different types
This file contains hidden or 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 BlockArguments #-} | |
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE ScopedTypeVariables #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE UndecidableInstances #-} | |
module Eqq where | |
-- An example of an equality class that works across different types | |
-- The current implementation is needed to pointer compare different objects (even if of different types) | |
import Data.Proxy (Proxy (..)) | |
import System.IO.Unsafe (unsafePerformIO) | |
import System.Mem.StableName (makeStableName) | |
-- It's possible to test for type equality using *closed* type families | |
-- Typeclasses are not able to do this | |
type family F a b :: Bool where | |
F a a = 'True | |
F _ _ = 'False | |
-- This is the desired class we want to implement | |
class Eqq a b where | |
eqq :: a -> b -> Bool | |
-- We define a decorated class which takes the equality information from the type level function | |
-- And then decides how to perform the equality operation | |
class Eqq' (flag :: Bool) a b where | |
eqq' :: Proxy flag -> a -> b -> Bool | |
-- Then we can dispatch automatically based on the type level function's result | |
instance (F a b ~ typesAreEq, Eqq' typesAreEq a b) => Eqq a b where | |
eqq = eqq' (Proxy :: Proxy typesAreEq) | |
-- Here's how to compare when the types are equal | |
instance Eqq' 'True a a where | |
eqq' _ a b = unsafePerformIO $ do | |
a1 <- makeStableName a | |
b1 <- makeStableName b | |
return (a1 == b1) | |
-- Here's how to compare when the types are not equal | |
-- Comparing unequal types always fails | |
instance Eqq' 'False a b where | |
eqq' _ _ _ = False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment