Giter VIP home page Giter VIP logo

open-union's Introduction

Intro

open-union adds type-safe extensible unions to Haskell, which can be used a la:

{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.OpenUnion

type MyUnion = Union (Char :| Int :| [()])

showMyUnion :: MyUnion -> String
showMyUnion
    =  (\(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

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

type TrackStates = '[Stopped, Recording, Playing]

startRecording
  :: 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.

N.B.

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 Void case, and using it as a catchall (or forgetting to provide a certain case, for instance) will result in an error like:

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

Types to the right of :\ have been handled.

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

example.hs:20:30:
    No instance for (Data.OpenUnion.Internal.LiftToUnion Void [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"

open-union's People

Contributors

bfops avatar rimmington avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.