Last active
February 15, 2018 17:04
-
-
Save neongreen/a7e859987ffdc477c0a51ae11343d9c2 to your computer and use it in GitHub Desktop.
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
| {-# 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