Skip to content

Instantly share code, notes, and snippets.

@andrevidela
Last active December 11, 2018 23:00
Show Gist options
  • Save andrevidela/b51d2671959be185e4bb6fe2c7ce6788 to your computer and use it in GitHub Desktop.
Save andrevidela/b51d2671959be185e4bb6fe2c7ce6788 to your computer and use it in GitHub Desktop.
How to select the correct instance for an indexed typeclass?
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables#-}
{-# LANGUAGE TypeApplications#-}
{-# LANGUAGE TypeFamilies #-}
data ValueKind = First | Second deriving (Eq, Show)
class DisplayClass (v :: ValueKind) where
type FromValue v :: *
makeValue :: FromValue v
displayName :: FromValue v -> String
instance DisplayClass First where
type FromValue First = Int
makeValue = 1
displayName = show
instance DisplayClass Second where
type FromValue Second = String
makeValue = "Second"
displayName = id
makeAndPrint :: forall v. (DisplayClass v) => IO ()
makeAndPrint = putStrLn $ displayName @v (makeValue @v)
main :: IO ()
main = do
let firstValue = First
let secondValue = Second
-- makeAndPrint --using firstValue Instance
-- makeAndPrint --ysing secondValue Instance
pure ()
@mstksg
Copy link

mstksg commented Dec 11, 2018

genSingletons [''ValueKind]

makeAndPrint :: forall v. Sing v -> IO ()
makeAndPrint SFirst = displayName @v (makeValue @v)
makeAndPrint SSecond = dispalyName @v (makeValue @v)

main :: IO ()
main = do
    let firstValue = First
    let secondValue = Second
    let thirdValue = First
    case toSing firstValue of                       -- existential wrapper method
      SomeSing s -> makeAndPrint s
    withSomeSing secondValue makeAndPrint           -- RankN continuation method
    case thirdValue of                              -- existential pattern synonym method
      FromSing s -> makeAndPrint s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment