The open-union package

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.



Extensible, type-safe unions. This package is very new and likely to change.

Basic usage example (language tags ommitted due to

 import Data.OpenUnion
 type MyUnion = Union '[Char, Int, [()]]
 showMyUnion :: MyUnion -> String
     =  (\(c :: Char) -> "char: " ++ show c)
     @> (\(i :: Int) -> "int: " ++ show i)
     @> (\(l :: [()]) -> "list length: " ++ show (length l))
     @> (\(s :: String) -> "string: " ++ s)
     @> typesExhausted
 main :: IO ()
 main = do
     putStrLn $ showMyUnion $ liftUnion (4 :: Int)
     putStrLn $ showMyUnion $ liftUnion 'a'
     putStrLn $ showMyUnion $ liftUnion [(), ()]

which prints:

 int: 4
 char: 'a'
 list length: 2

Casting to an unrelated type does not cause errors; In the above example,showMyUnion contains a String case despite MyUnion not containing String - superfluous cases are ignored, for the time being.

typesExhausted is NOT a catchall. It is a null case, and using it as a catchall (or forgetting to provide a certain case, for instance) will result in an error like:

     Couldn't match type ‘Int : ('[] :\ [Char])’ with ‘'[]’
     Expected type: Union ('[Int] :\ String) -> String
       Actual type: Union '[] -> String
     In the second argument of ‘(@>)’, namely ‘typesExhausted’
     In the second argument of ‘(@>)’, namely
       ‘(\ (s :: String) -> "string: " ++ s) @> typesExhausted’

The left-hand parts of the ': (think type-level `(:)`) are the cases that still need to be satisfied.

Trying to lift an incorrect type to a Union will cause an error resembling:

     No instance for (Data.OpenUnion.Internal.LiftToUnion '[] [Char])
       arising from a use of ‘liftUnion’
     In the second argument of ‘($)’, namely ‘liftUnion "asdf"’
     In the second argument of ‘($)’, namely
       ‘showMyUnion $ liftUnion "asdf"’
     In a stmt of a 'do' block:
       putStrLn $ showMyUnion $ liftUnion "asdf"

The original use case for this library was code like this (snipped from some record/playback logic):

 type TrackStates = '[Stopped, Recording, Playing]

   :: Union (TrackStates :\ Recording)
   -> ([Note], Union '[Recording])

The `(:)` type-level operator is for removal from a set, i.e. startRecording can be applied to a track in any state except the Recording state.


Change logNone available
Dependenciesbase (==4.*), open-union [details]
AuthorBen Foppa
Home page
Source repositoryhead: git clone
UploadedMon Jun 30 15:32:31 UTC 2014 by BenFoppa



Maintainers' corner

For package maintainers and hackage trustees