Skip to content

Instantly share code, notes, and snippets.

@neongreen
Last active February 15, 2018 17:04
Show Gist options
  • Select an option

  • Save neongreen/a7e859987ffdc477c0a51ae11343d9c2 to your computer and use it in GitHub Desktop.

Select an option

Save neongreen/a7e859987ffdc477c0a51ae11343d9c2 to your computer and use it in GitHub Desktop.
{-# OPTIONS -Wall #-}
{-# LANGUAGE FlexibleContexts #-} -- not all of these are needed
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-} -- really
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-} -- don't get scared
{-# 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