Module

Option

Package
purescript-option
Repository
joneshf/purescript-option

There are a few different data types that encapsulate ideas in programming.

Records capture the idea of a collection of key/value pairs where every key and value exist. E.g. Record (foo :: Boolean, bar :: Int) means that both foo and bar exist and with values all of the time.

Variants capture the idea of a collection of key/value pairs where exactly one of the key/value pairs exist. E.g. Variant (foo :: Boolean, bar :: Int) means that either only foo exists with a value or only bar exists with a value, but not both at the same time.

Options capture the idea of a collection of key/value pairs where any key and value may or may not exist. E.g. Option (foo :: Boolean, bar :: Int) means that either only foo exists with a value, only bar exists with a value, both foo and bar exist with values, or neither foo nor bar exist.

The distinction between these data types means that we can describe problems more accurately. Options are typically what you find in dynamic languages or in weakly-typed static languages. Their use cases range from making APIs more flexible to interfacing with serialization formats to providing better ergonomics around data types.

#Option Source

newtype Option (row :: # Type)

A collection of key/value pairs where any key and value may or may not exist. E.g. Option (foo :: Boolean, bar :: Int) means that either only foo exists with a value, only bar exists with a value, both foo and bar exist with values, or neither foo nor bar exist.

Instances

  • (DecodeJsonOption list option, RowToList option list) => DecodeJson (Option option)

    This instance ignores keys that do not exist in the given JSON object.

    If a key does not exist in the JSON object, it will not be added to the Option _.

    If a key does exists in the JSON object but the value cannot be successfully decoded, it will fail with an error.

    If a key does exists in the JSON object and the value can be successfully decoded, it will be added to the Option _.

  • (EncodeJsonOption list option, RowToList option list) => EncodeJson (Option option)

    This instance ignores keys that do not exist.

    If a key does not exist in the given Option _, it is not added to the JSON object.

    If a key does exists in the given Option _, it encodes it like normal and adds it to the JSON object.

  • (EqOption list option, RowToList option list) => Eq (Option option)
  • (OrdOption list option, RowToList option list) => Ord (Option option)
  • (RowToList option list, ReadForeignOption list option) => ReadForeign (Option option)

    This instance ignores keys that do not exist in the given Foreign.

    If a key does not exist in the Foreign, it will not be added to the Option _.

    If a key does exists in the Foreign but the value cannot be successfully read, it will fail with an error.

    If a key does exists in the Foreign and the value can be successfully read, it will be added to the Option _.

  • (RowToList option list, ShowOption list option) => Show (Option option)
  • (RowToList option list, WriteForeignOption list option) => WriteForeign (Option option)

    This instance ignores keys that do not exist.

    If a key does not exist in the given Option _, it is not added to the Foreign.

    If a key does exists in the given Option _, it writes it like normal and adds it to the Foreign.

#fromRecord Source

fromRecord :: forall option record. FromRecord record option => Record record -> Option option

The given Record record must have no more fields than the expected Option _.

E.g. The following definitions are valid.

option1 :: Option.Option ( foo :: Boolean, bar :: Int )
option1 = Option.fromRecord' { foo: true, bar: 31 }

option2 :: Option.Option ( foo :: Boolean, bar :: Int )
option2 = Option.fromRecord' {}

However, the following definitions are not valid as the given records have more fields than the expected Option _.

-- This will not work as it has the extra field `baz`
option3 :: Option.Option ( foo :: Boolean, bar :: Int )
option3 = Option.fromRecord' { foo: true, bar: 31, baz: "hi" }

-- This will not work as it has the extra field `qux`
option4 :: Option.Option ( foo :: Boolean, bar :: Int )
option4 = Option.fromRecord' { qux: [] }

This is an alias for fromRecord' so the documentation is a bit clearer.

#delete Source

delete :: forall label option option' proxy value. IsSymbol label => Cons label value option option' => Lacks label option => proxy label -> Option option' -> Option option

Removes a key from an option

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.fromRecord { foo: true, bar: 31 }

anotherOption :: Option.Option ( bar :: Int )
anotherOption = Option.delete (Data.Symbol.SProxy :: _ "foo") someOption

The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

#empty Source

empty :: forall option. Option option

Creates an option with no key/values that matches any type of option.

This can be useful as a starting point for an option that is later built up.

E.g.

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.empty

anotherOption :: Option.Option ( foo :: Boolean, bar :: Int )
anotherOption = Option.insert (Data.Symbol.SProxy :: _ "bar") 31 Option.empty

#get Source

get :: forall label option option' proxy value. IsSymbol label => Cons label value option' option => proxy label -> Option option -> Maybe value

Attempts to fetch the value at the given key from an option.

If the key exists in the option, Just _ is returned.

If the key does not exist in the option, Nothing is returned.

E.g.

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.insert (Data.Symbol.SProxy :: _ "bar") 31 Option.empty

bar :: Data.Maybe.Maybe Int
bar = Option.get (Data.Symbol.SProxy :: _ "bar") someOption

The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

#getWithDefault Source

getWithDefault :: forall label option option' proxy value. IsSymbol label => Cons label value option' option => value -> proxy label -> Option option -> value

Attempts to fetch the value at the given key from an option falling back to the default.

If the key exists in the option, Just _ is returned.

If the key does not exist in the option, Nothing is returned.

E.g.

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.insert (Data.Symbol.SProxy :: _ "bar") 31 Option.empty

bar :: Data.Maybe.Maybe Int
bar = Option.get (Data.Symbol.SProxy :: _ "bar") someOption

The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

#insert Source

insert :: forall label option option' proxy value. IsSymbol label => Cons label value option' option => Lacks label option' => proxy label -> value -> Option option' -> Option option

Adds a new key with the given value to an option. The key must not already exist in the option. If the key might already exist in the option, set should be used instead.

E.g.

someOption :: Option.Option ( foo :: Boolean )
someOption = Option.empty

anotherOption :: Option.Option ( foo :: Boolean, bar :: Int )
anotherOption = Option.insert (Data.Symbol.SProxy :: _ "bar") 31 someOption

The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

#jsonCodec Source

jsonCodec :: forall option record. JsonCodec record option => String -> Record record -> JsonCodec (Option option)

Creates a JsonCodec for an Option _ given a Record _ of JsonCodecs.

The String is used in errors when decoding fails.

E.g.

type Example
  = Option.Option
      ( foo :: Boolean
      , bar :: Int
      )

jsonCodec :: Data.Codec.Argonaut.JsonCodec Example
jsonCodec =
  Option.jsonCodec
    "Example"
    { foo: Data.Codec.Argonaut.boolean
    , bar: Data.Codec.Argonaut.int
    }

This is an alias for jsonCodec' so the documentation is a bit clearer.

#modify Source

modify :: forall label option option' option'' proxy value value'. IsSymbol label => Cons label value' option'' option' => Cons label value option'' option => proxy label -> (value' -> value) -> Option option' -> Option option

Manipulates the value of a key in an option.

If the field exists in the option, the given function is applied to the value.

If the field does not exist in the option, there is no change to the option.

E.g.

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.insert (Data.Symbol.SProxy :: _ "bar") 31 Option.empty

anotherOption :: Option.Option ( foo :: Boolean, bar :: Int )
anotherOption = Option.modify (Data.Symbol.SProxy :: _ "bar") (_ + 1) someOption

The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

#set Source

set :: forall label option option' option'' proxy value value'. IsSymbol label => Cons label value' option'' option' => Cons label value option'' option => proxy label -> value -> Option option' -> Option option

Changes a key with the given value to an option. The key must already exist in the option. If the key might not already exist in the option, insert should be used instead.

E.g.

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.empty

anotherOption :: Option.Option ( foo :: Boolean, bar :: Int )
anotherOption = Option.set (Data.Symbol.SProxy :: _ "bar") 31 someOption

The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

#toRecord Source

toRecord :: forall option record. ToRecord option record => Option option -> Record record

The expected Record record will have the same fields as the given Option _ where each type is wrapped in a Maybe.

E.g.

someOption :: Option.Option ( foo :: Boolean, bar :: Int )
someOption = Option.fromRecord' { foo: true, bar: 31 }

someRecord :: Record ( foo :: Data.Maybe.Maybe Boolean, bar :: Data.Maybe.Maybe Int )
someRecord = Option.toRecord' someOption

#DecodeJsonOption Source

class DecodeJsonOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList decoding an Object Json to an Option _.

Members

  • decodeJsonOption :: forall proxy. proxy list -> Object Json -> Either String (Option option)

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#EncodeJsonOption Source

class EncodeJsonOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList encoding an Option _ as Json.

Members

  • encodeJsonOption :: forall proxy. proxy list -> Option option -> Json

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#EqOption Source

class EqOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList converting an Option _ to a Boolean.

Members

  • eqOption :: forall proxy. proxy list -> Option option -> Option option -> Boolean

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#FromRecord Source

class FromRecord (record :: # Type) (option :: # Type)  where

A typeclass for converting a Record _ into an Option _.

An instance FromRecord record option states that we can make an Option option from a Record record where every field present in the record is present in the option. E.g. FromRecord () ( name :: String ) says that the Option ( name :: String ) will have no value; and FromRecord ( name :: String ) ( name :: String ) says that the Option ( name :: String ) will have the given name value.

Since there is syntax for creating records, but no syntax for creating options, this typeclass can be useful for providing an easier to use interface to options.

E.g. Someone can say:

Option.fromRecord' { foo: true, bar: 31 }

Instead of having to say:

Option.insert
  (Data.Symbol.SProxy :: _ "foo")
  true
  ( Option.insert
      (Data.Symbol.SProxy :: _ "bar")
      31
      Option.empty
  )

Not only does it save a bunch of typing, it also mitigates the need for a direct dependency on SProxy _.

Members

  • fromRecord' :: Record record -> Option option

    The given Record record must have no more fields than the expected Option _.

    E.g. The following definitions are valid.

    option1 :: Option.Option ( foo :: Boolean, bar :: Int )
    option1 = Option.fromRecord' { foo: true, bar: 31 }
    
    option2 :: Option.Option ( foo :: Boolean, bar :: Int )
    option2 = Option.fromRecord' {}
    

    However, the following definitions are not valid as the given records have more fields than the expected Option _.

    -- This will not work as it has the extra field `baz`
    option3 :: Option.Option ( foo :: Boolean, bar :: Int )
    option3 = Option.fromRecord' { foo: true, bar: 31, baz: "hi" }
    
    -- This will not work as it has the extra field `qux`
    option4 :: Option.Option ( foo :: Boolean, bar :: Int )
    option4 = Option.fromRecord' { qux: [] }
    

Instances

  • (FromRecordOption list record option, RowToList record list) => FromRecord record option

    This instance converts a record into an option.

    Every field in the record is added to the option.

    Any fields in the expected option that do not exist in the record are not added.

#FromRecordOption Source

class FromRecordOption (list :: RowList) (record :: # Type) (option :: # Type) | list -> option record where

A typeclass that iterates a RowList converting a Record _ into an Option _.

Members

  • fromRecordOption :: forall proxy. proxy list -> Record record -> Option option

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#JsonCodec Source

class JsonCodec (record :: # Type) (option :: # Type)  where

A typeclass that converts a record of JsonCodecs into a JsonCodec for an option.

This is useful to provide a straight-forward JsonCodec for an Option _.

Members

  • jsonCodec' :: String -> Record record -> JsonCodec (Option option)

    Creates a JsonCodec for an Option _ given a Record _ of JsonCodecs.

    E.g. The String is used in errors when decoding fails.

    type Example
      = Option.Option
          ( foo :: Boolean
          , bar :: Int
          )
    
    jsonCodec :: Data.Codec.Argonaut.JsonCodec Example
    jsonCodec =
      Option.jsonCodec
        "Example"
        { foo: Data.Codec.Argonaut.boolean
        , bar: Data.Codec.Argonaut.int
        }
    

Instances

  • (JsonCodecOption list record option, RowToList record list) => JsonCodec record option

    This instance ignores keys that do not exist in the given JSON object and does not insert keys that do not exist in the given Option _.

    If a key does not exist in the JSON object, it will not be added to the Option _.

    If a key does exists in the JSON object but the value cannot be successfully decoded, it will fail with an error.

    If a key does exists in the JSON object and the value can be successfully decoded, it will be added to the Option _.

    If a key does not exist in the given Option _, it is not added to the JSON object.

    If a key does exists in the given Option _, it encodes it like normal and adds it to the JSON object.

#JsonCodecOption Source

class JsonCodecOption (list :: RowList) (record :: # Type) (option :: # Type) | list -> option record where

A typeclass that iterates a RowList converting a record of JsonCodecs into a JsonCodec for an option.

Members

  • jsonCodecOption :: forall proxy. proxy list -> Record record -> JPropCodec (Option option)

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#OrdOption Source

class (EqOption list option) <= OrdOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList converting an Option _ to a Boolean.

Members

  • compareOption :: forall proxy. proxy list -> Option option -> Option option -> Ordering

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#ReadForeignOption Source

class ReadForeignOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList attempting to read a Foreign to an Option _.

Members

  • readImplOption :: forall proxy. proxy list -> Foreign -> F (Option option)

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#ShowOption Source

class ShowOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList converting an Option _ to a List String. The List String should be processed into a single String.

Members

  • showOption :: forall proxy. proxy list -> Option option -> List String

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#ToRecord Source

class ToRecord (option :: # Type) (record :: # Type) | option -> record where

A typeclass for converting an Option _ into a Record _.

Since there is syntax for operating on records, but no syntax for operating on options, this typeclass can be useful for providing an easier to use interface to options.

E.g. Someone can say:

(Option.toRecord' someOption).foo

Instead of having to say:

Option.get (Data.Symbol.SProxy :: _ "foo") someOption

Not only does it save a bunch of typing, it also mitigates the need for a direct dependency on SProxy _.

Members

  • toRecord' :: Option option -> Record record

    The expected Record record will have the same fields as the given Option _ where each type is wrapped in a Maybe.

    E.g.

    someOption :: Option.Option ( foo :: Boolean, bar :: Int )
    someOption = Option.fromRecord' { foo: true, bar: 31 }
    
    someRecord :: Record ( foo :: Data.Maybe.Maybe Boolean, bar :: Data.Maybe.Maybe Int )
    someRecord = Option.toRecord' someOption
    

Instances

  • (ToRecordOption list option record, RowToList record list) => ToRecord option record

    This instance converts an option into a record.

    Every field in the option is added to a record with a Maybe _ type.

    All fields in the option that exist will have the value Just _. All fields in the option that do not exist will have the value Nothing.

#ToRecordOption Source

class ToRecordOption (list :: RowList) (option :: # Type) (record :: # Type) | list -> option record where

A typeclass that iterates a RowList converting an Option _ into a Record _.

Members

  • toRecordOption :: forall proxy. proxy list -> Option option -> Record record

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

#WriteForeignOption Source

class WriteForeignOption (list :: RowList) (option :: # Type) | list -> option where

A typeclass that iterates a RowList writing an Option _ to a Foreign.

Members

  • writeForeignOption :: forall proxy. proxy list -> Option option -> Foreign

    The proxy can be anything so long as its type variable has kind Prim.RowList.RowList.

    It will commonly be Type.Data.RowList.RLProxy, but doesn't have to be.

Instances

Modules
Option