Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rowtype-yoga/purescript-untagged-union
A Purescript data type for untagged unions
https://github.com/rowtype-yoga/purescript-untagged-union
Last synced: 3 months ago
JSON representation
A Purescript data type for untagged unions
- Host: GitHub
- URL: https://github.com/rowtype-yoga/purescript-untagged-union
- Owner: rowtype-yoga
- License: mit
- Created: 2019-11-13T05:36:00.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2022-12-10T09:13:00.000Z (almost 2 years ago)
- Last Synced: 2024-05-08T00:35:11.608Z (6 months ago)
- Language: PureScript
- Size: 122 KB
- Stars: 48
- Watchers: 2
- Forks: 6
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-purescript - untagged-union - A data type for untagged unions. (Data types)
README
# purescript-untagged-union
A data type for untagged unions.
# Overview
Consider a the following type:
```purescript
import Untagged.Uniontype ISB = Int |+| String |+| Boolean
```The type `ISB` describes values which can either be an `Int`, a `String` or a `Boolean`. Moreover, it is guaranteed that at runtime, values of type `ISB` is directly stored as an `Int`, a `String` or a `Boolean` without any wrappers. This makes it especially useful for FFI.
Note that `|+|` is an alias for `OneOf`.
## Creating a `OneOf`
In order to create a value of `OneOf`, use `asOneOf`.
```purescript
isb1 :: ISB
isb1 = asOneOf 20isb2 :: ISB
isb2 = asOneOf "foo"--isb3 :: ISB
--isb3 = asOneOf 3.5-- isb3 will fail since 3.5 is a Number which is neither
-- an Int, String nor Boolean```
## Usage with Undefined
The library also defines `Undefined`. Combined with `OneOf`, it can represent an optional type:
```purescript
import Literals.Undefinedtype OptionalInt = Undefined |+| Int
```An alias `UndefinedOr` is also provided.
```purescript
type OptionalInt' = UndefinedOr Int -- Same as `Undefined |+| Int`
```## Getting a value
To get a purescript value back, use `fromOneOf`:
```purescript
import Data.MaybevalInt :: Maybe Int
valInt = fromOneOf isb1 -- evaluates to `Just 20`valString :: Maybe String
valString = fromOneOf isb1 -- evalutes to `Nothing` since isb1 contains an Int```
## Usage with records
Using `OneOf`, describing JS types as records becomes intuitive:
```purescript
type Props =
{ text :: String -- a required field-- Optional Fields
, width :: UndefinedOr Number
, height :: UndefinedOr Number-- Optional and Varying types
, fontSize :: Undefined |+| String |+| Number
}
```A `cast` helper is made available to convert records with the same runtime value:
```purescript
import Untagged.Castable (cast)sampleProps :: Props
sampleProps =
cast { text: "foo" -- text is required and should be a string, width: 30.0 -- width is optional, and may be defined, but should be a Number
-- height is optional and may be omitted
, fontSize: "100%" -- fontSize may be defined, and should either be a string or number
}```
## Nested Unions
Nesting is possible but requires some hints for the compiler.
Consider the following:
```purescript
type Props =
{ text :: String -- a required field
, width :: UndefinedOr Number
, height :: UndefinedOr Number
, fontSize :: Undefined |+| String |+| Number
}type ContainerProps =
{ titleProps :: UndefinedOr Props
, opacity :: UndefinedOr Number
}
```In order to create an instance of `ContainerProps`, the type of titleProps must be specified.
```purescript
sampleContainerProps :: ContainerProps
sampleContainerProps =
cast { titleProps: (cast { text: "Foo" } :: Props)
}
```Alternatively, helper constructors may be used to aid type inference.
```purescript
import Untagged.Castable (Castable)props :: forall r. Castable r Props => r -> Props
props = castcontainerProps :: forall r. Castable r ContainerProps => r -> ContainerProps
containerProps = castsampleContainerProps' :: ContainerProps
sampleContainerProps' =
containerProps { titleProps: props { text: "Foo" }
}
```