std.prelude

Definitions which gets implicit re-export in every file.

Types

type IO a = <opaque>

type Ordering = 
    | LT
    | EQ
    | GT

Ordering represents the result of comparing two values

#[implicit]
type Semigroup a = { append : a -> a -> a }

Semigroup a represents an associative operation on a. This means the following laws must hold:

  • forall x . append x (append y z) == append (append x y) z

#[implicit]
type Monoid a = { semigroup : Semigroup a, empty : a }

Monoid a represents an semigroup an which has an identity. This means the following additional laws must hold:

  • forall x . append x empty == x
  • forall x . append empty x == x

#[implicit]
type Group a = { monoid : Monoid a, inverse : a -> a }

Group a represents an monoid an which has an inverse element. This means the following additional laws must hold:

  • forall x . append (inverse x) x = empty = append x (inverse x)

#[implicit]
type Eq a = { (==) : a -> a -> Bool }

Eq a defines equality (==) on a

#[implicit]
type Ord a = { eq : Eq a, compare : a -> a -> Ordering }

Ord a defines an ordering on a

#[implicit]
type Category cat = {
    id : forall a . cat a a,
    compose : forall a b c . cat b c -> cat a b -> cat a c
}

#[implicit]
type Functor f = { map : forall a b . (a -> b) -> f a -> f b }

A Functor represents an action on a parameterized type which does not change the structure with the mapped type.

The following laws should hold:

  • map id == id
  • map (f << g) == map f << map g

#[implicit]
type Applicative f = {
    functor : Functor f,
    apply : forall a b . f (a -> b) -> f a -> f b,
    wrap : forall a . a -> f a
}

A Functor with application.

The following laws should hold:

  • wrap id <*> v = v
  • wrap (<<) <*> u <*> v <*> w = u <*> (v <*> w)
  • wrap f <*> wrap x = wrap (f x)
  • u <*> wrap y = wrap (\g -> g x) <*> u

#[implicit]
type Alternative f = {
    applicative : Applicative f,
    empty : forall a . f a,
    or : forall a . f a -> f a -> f a
}

A monoid on applicative functors.

#[implicit]
type Monad m = {
    applicative : Applicative m,
    flat_map : forall a b . (a -> m b) -> m a -> m b
}

A generalised interface for imperatively sequencing actions

#[implicit]
type Num a = {
    ord : Ord a,
    (+) : a -> a -> a,
    (-) : a -> a -> a,
    (*) : a -> a -> a,
    (/) : a -> a -> a,
    negate : a -> a
}

The basic operation on numbers. Defined for both the primitive type Int and Float

#[implicit]
type Show a = { show : a -> String }

Show a represents a conversion function from a to a readable string.

type Option a = 
    | None
    | Some a

Option represents a value which may not exist.

type Bool = 
    | False
    | True

Bool represents a value which can only be True or False

type Array a = Array a

Values

let append ?s : forall a . [Semigroup a] -> a -> a -> a

Note
  • Known as (<>) or mappend in Haskell

#[infix(left, 4)]
let <> : forall a . [Semigroup a] -> a -> a -> a

let empty ?m : forall a . [Monoid a] -> a

Note
  • Known as mempty in Haskell

#[infix(left, 4)]
let == ?eq : forall a . [Eq a] -> a -> a -> Bool

Tests whether the values are equal.

#[infix(left, 4)]
let /= ?eq l r : forall a . [Eq a] -> a -> a -> Bool

Tests whether the values are not equal.

#[infix(left, 4)]
let < l r : forall a . [Ord a] -> a -> a -> Bool

Returns whether l is less than r.

#[infix(left, 4)]
let <= l r : forall a . [Ord a] -> a -> a -> Bool

Returns whether l is less than or equal to r.

#[infix(left, 4)]
let >= l r : forall a . [Ord a] -> a -> a -> Bool

Returns whether l is greater than or equal to r.

#[infix(left, 4)]
let > l r : forall a . [Ord a] -> a -> a -> Bool

Returns whether l is greater than r.

let id ?cat : forall cat a . [Category cat] -> cat a a

let compose ?cat : forall cat . forall a b c . [Category cat] -> cat b c -> cat a b -> cat a c

#[infix(left, 6)]
let + ?num : forall a . [Num a] -> a -> a -> a

The addition operator

#[infix(left, 6)]
let - ?num : forall a . [Num a] -> a -> a -> a

The subtraction operator

#[infix(left, 7)]
let * ?num : forall a . [Num a] -> a -> a -> a

The multiplication operator

#[infix(left, 7)]
let / ?num : forall a . [Num a] -> a -> a -> a

The division operator

let negate ?num : forall a . [Num a] -> a -> a

The negation function

let show ?s : forall a . [Show a] -> a -> String

Converts a value into a string.

let { ? } = import! std.effect
let { assert_eq, ? } = import! std.test
let list @ { ? } = import! std.list

seq assert_eq (show 123) "123"
seq assert_eq (show 3.14) "3.14"
seq assert_eq (show "abc") "\"abc\""
assert_eq (show (list.of [1, 2, 3])) "[1, 2, 3]"

#[infix(left, 4)]
let ++ : String -> String -> String

Appends two strings.

Re-export of semigroup.append.

let not x : Bool -> Bool

Boolean 'not'

let error : forall a . String -> a

let flat_map ?m : forall b a m . [Monad m] -> (a -> m b) -> m a -> m b

This can be seen as akin to sequential variable binding in an imperative language. For example in Javascript:

var x = call_fallible("hello");
do_something(x);

In gluon this would look like:

result.monad.flat_map (\x -> do_something x) (call_fallible "hello")

Note that it is sometimes more ergonomic to use the (>>=) operator:

let { (>>=) } = import! std.prelude

call_fallible "hello" >>= (\x -> do_something x)
Note
  • Known as (=<<) or flip (>>=)` in Haskell
  • Known as Option::and_then and Result::and_then in Rust