Last active
August 21, 2017 12:00
-
-
Save cblp/b9e0d3aac0ab8e496a9930d74e3b8f57 to your computer and use it in GitHub Desktop.
Example of usage of an existential type as a sum type.
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
#!/usr/bin/env stack | |
-- stack --resolver=lts-9.0 script --package=singletons | |
{-# OPTIONS_GHC -Wall -Werror #-} | |
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE ExistentialQuantification #-} | |
{-# LANGUAGE LambdaCase #-} | |
{-# LANGUAGE PolyKinds #-} | |
{-# LANGUAGE Rank2Types #-} | |
{-# LANGUAGE ScopedTypeVariables #-} | |
{-# LANGUAGE TemplateHaskell #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE TypeInType #-} | |
import Data.Kind (Type) | |
import Data.Singletons (Sing, SingI, sing) | |
import Data.Singletons.TH (genSingletons) | |
data LetterName = Alpha | Beta | |
genSingletons [''LetterName] | |
data family LetterSpecific :: LetterName -> Type | |
data instance LetterSpecific 'Alpha = LetterAlpha Int | |
data instance LetterSpecific 'Beta = LetterBeta Char | |
data Letter | |
= forall (letter :: LetterName) | |
. SingI letter => Letter (LetterSpecific letter) | |
matchLetter | |
:: (forall letter . (Sing letter, LetterSpecific letter) -> a) | |
-> Letter | |
-> a | |
matchLetter go (Letter (spec :: LetterSpecific letter)) = | |
go (sing :: Sing letter, spec) | |
extract :: Letter -> String | |
extract = matchLetter $ \case | |
(SAlpha, LetterAlpha int ) -> "alpha " ++ show int | |
(SBeta , LetterBeta char) -> "beta " ++ [char] | |
main :: IO () | |
main = print $ map extract [Letter $ LetterAlpha 1, Letter $ LetterBeta 'B'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment