-
-
Save joshburgess/6f8b86b36d4ba571bd03eaa4452ba85c to your computer and use it in GitHub Desktop.
Union types (with explicit upcast) in Haskell
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
-- Example usage | |
module Main where | |
import Union | |
unionValue1 :: Union (String, (Double, ((Int, Int), ()))) | |
unionValue1 = mkUnion "Foo" | |
unionValue2 :: Union (String, (Double, ((Int, Int), ()))) | |
unionValue2 = upcast (mkUnion 1.5) | |
unionValue3 :: Union (String, (Double, ((Int, Int), ()))) | |
unionValue3 = upcast (upcast (mkUnion (4,5))) | |
showFirst :: Union (String, (Double, ((Int, Int), ()))) -> String | |
showFirst union = case typeCase union of | |
Left string -> string | |
Right union' -> case typeCase union' of | |
Left double -> show double | |
Right union'' -> case finalCase union'' of | |
(x,y) -> show x | |
-- | | |
-- >>> main | |
-- 4 | |
main :: IO () | |
main = do print (showFirst unionValue1) | |
print (showFirst unionValue2) | |
print (showFirst unionValue3) |
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
{-# LANGUAGE ExistentialQuantification #-} | |
module Union (Union, mkUnion, upcast, typeCase, finalCase) where | |
import Data.Typeable | |
data Union u = forall a. Typeable a => PrivateUnion a | |
mkUnion :: Typeable a => a -> Union (a, u) | |
mkUnion x = PrivateUnion x | |
upcast :: Typeable a => Union u -> Union (a, u) | |
upcast (PrivateUnion x) = PrivateUnion x | |
typeCase :: Typeable a => Union (a, u) -> Either a (Union u) | |
typeCase (PrivateUnion x) = case cast x of | |
Just y -> Left y | |
Nothing -> Right (PrivateUnion x) | |
finalCase :: Typeable a => Union (a, ()) -> a | |
finalCase union = case typeCase union of | |
Left x -> x | |
Right y -> y `seq` error msg | |
where | |
msg = "never happens, as a Union () cannot be constructed." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment