Skip to content

Instantly share code, notes, and snippets.

@neongreen
Created February 15, 2018 16:57
Show Gist options
  • Save neongreen/63dbf00821bca1d00456bd346bff0210 to your computer and use it in GitHub Desktop.
Save neongreen/63dbf00821bca1d00456bd346bff0210 to your computer and use it in GitHub Desktop.
{-# OPTIONS -Wall #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE MagicHash #-}
import GHC.TypeLits
import GHC.OverloadedLabels
import GHC.Prim
----------------------------------------------------------------------------
-- main
----------------------------------------------------------------------------
main :: IO ()
main = say #hi >> say #bye
say :: OneOf ["hi", "bye"] -> IO ()
say (#hi -> True) = putStrLn "Hello world!"
say (#bye -> True) = putStrLn "Goodbye!"
----------------------------------------------------------------------------
-- Implementation
----------------------------------------------------------------------------
instance {-# OVERLAPPING #-}
IsLabel name (OneOf (name : xs)) where
fromLabel _ = OneOf 0
-- TODO: can be optimized to O(1) by doing all the work at the typelevel
instance {-# OVERLAPPABLE #-}
IsLabel name (OneOf xs) => IsLabel name (OneOf (y : xs)) where
fromLabel _ = let OneOf n = fromLabel @name @(OneOf xs) proxy#
in OneOf (n+1)
instance IsLabel name (OneOf xs) => IsLabel name (OneOf xs -> Bool) where
fromLabel _ = (== fromLabel @name @(OneOf xs) proxy#)
data OneOf (names :: [Symbol]) = OneOf Int
deriving Eq
{-
data Atom (name :: Symbol) = Atom
instance IsLabel name (Atom name) where
fromLabel _ = Atom
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment