Morgan-Stanley/morphir-elm/2.0.0

NOTE: the latest version is 3.0.0

Renamed to finos/morphir-elm. It is published under that name, and new versions come out there.

Versions published as Morgan-Stanley/morphir-elm still install under that name. 5 versions of 5 come from the new location (see their notes).

Rerouted (fork, verified). The original repository is gone. This copy comes from a fork that still has the tag. The Lamdera package server serves a copy recovered from https://github.com/maoo/morphir-elm (a fork).

What we checked: Rebuilt with git archive from commit 51e7ceb666e5 of https://github.com/maoo/morphir-elm (a fork) (zip prefix Morgan-Stanley-morphir-elm-c0a167e/, America/Los_Angeles times): the zip is byte-identical to the one package.elm-lang.org recorded, SHA-1 a573dab6e577d8aa40585d10959c1dccb7b8f000.

The Lamdera compiler uses this copy and prints a one-line notice saying so. elm itself fails to download this version.

Details · package.elm-lang.org's zip: https://github.com/Morgan-Stanley/morphir-elm/zipball/2.0.0/

Morphir.IR.Value

This module contains the building blocks of values in the Morphir IR.

Value

Value is the top level building block for data and logic. See the constructor functions below for details on each node type.

type Value a
= Literal a Literal
| Constructor a FQName
| Tuple a (List (Value a))
| List a (List (Value a))
| Record a (List ( Name, Value a ))
| Variable a Name
| Reference a FQName
| Field a (Value a) Name
| FieldFunction a Name
| Apply a (Value a) (Value a)
| Lambda a (Pattern a) (Value a)
| LetDefinition a Name (Definition a) (Value a)
| LetRecursion a (Dict Name (Definition a)) (Value a)
| Destructure a (Pattern a) (Value a) (Value a)
| IfThenElse a (Value a) (Value a) (Value a)
| PatternMatch a (Value a) (List ( Pattern a, Value a ))
| UpdateRecord a (Value a) (List ( Name, Value a ))
| Unit a

Type that represents a value.

literal : a -> Literal -> Value a

A literal represents a fixed value in the IR. We only allow values of basic types: bool, char, string, int, float.

True -- Literal (BoolLiteral True)


'a' -- Literal (CharLiteral 'a')


"foo" -- Literal (StringLiteral "foo")


13 -- Literal (IntLiteral 13)


15.4 -- Literal (FloatLiteral 15.4)

A reference to a constructor of a custom type.

Nothing -- Constructor ( ..., [ [ "maybe" ] ], [ "nothing" ] )


Foo.Bar -- Constructor ( ..., [ [ "foo" ] ], [ "bar" ] )
apply : a -> Value a -> Value a -> Value a

Represents a function invocation. We use currying to represent function invocations with multiple arguments.

Note: Operators are mapped to well-known function names.

not True -- Apply (Reference ( ..., [ [ "basics" ] ], [ "not" ])) (Literal (BoolLiteral True))


True || False -- Apply (Apply (Reference ( ..., [ [ "basics" ] ], [ "and" ]))) (Literal (BoolLiteral True)) (Literal (BoolLiteral True))
field : a -> Value a -> Name -> Value a

Extracts the value of a record's field.

a.foo -- Field (Variable [ "a" ]) [ "foo" ]
fieldFunction : a -> Name -> Value a

Represents a function that extract a field from a record value passed to it.

.foo -- FieldFunction [ "foo" ]
lambda : a -> Pattern a -> Value a -> Value a

Represents a lambda abstraction.

Note:

  • We use currying to represent lambda abstractions with multiple arguments.
  • Arguments are not just names, they are patterns.
\a -> a -- Lambda (AsPattern WildcardPattern [ "a" ]) (Variable [ "a" ])

\a b -> a -- Lambda (AsPattern WildcardPattern [ "a" ]) (Lambda (AsPattern WildcardPattern [ "b" ]) (Variable [ "a" ]))
letDef : a -> Name -> Definition a -> Value a -> Value a

Represents a let expression that assigns a value (and optionally type) to a name.

Note: We use currying to represent let expressions with multiple name bindings.

let
    a =
        b
in
a
-- LetDef [ "a" ]
--     (UntypedDefinition [] (Variable [ "b" ]))
--     (Variable [ "a" ])


let
    a : Bool
    a =
        b


    c x =
        a
in
c
-- LetDef [ "a" ]
--     (TypedDefinition (Basic BoolType) [] (Variable [ "b" ]))
--     (LetDef [ "c" ]
--         (UntypedDefinition [ [ "x" ] ] (Variable [ "a" ]))
--         (Variable [ "c" ])
--     )
letDestruct : a -> Pattern a -> Value a -> Value a -> Value a

Represents a let expression that extracts values using a pattern.

let
    ( a, b ) =
        c
in
a
-- LetDestruct
--     (TuplePattern [ AsPattern WildcardPattern ["a"], AsPattern WildcardPattern ["b"] ])
--     (Variable ["a"])
letRec : a -> Dict Name (Definition a) -> Value a -> Value a

Represents a let expression with one or many recursive definitions.

let
    a =
        b


    b =
        a
in
a
-- LetRec
--     [ ( [ "a" ], UntypedDefinition [] (Variable [ "b" ]) )
--     , ( [ "b" ], UntypedDefinition [] (Variable [ "a" ]) )
--     ]
--     (Variable [ "a" ])
list : a -> List (Value a) -> Value a

A list represents an ordered list of values where every value has to be of the same type.

[ 1, 3, 5 ] -- List [ Literal (IntLiteral 1), Literal (IntLiteral 3), Literal (IntLiteral 5) ]


[] -- List []
record : a -> List ( Name, Value a ) -> Value a

A record represents a list of fields where each field has a name and a value.

{ foo = "bar" } -- Record [ ( [ "foo" ], Literal (StringLiteral "bar") ) ]


{ foo = "bar", baz = 1 } -- Record [ ( [ "foo" ], Literal (StringLiteral "bar") ), ( [ "baz" ], Literal (IntLiteral 1) ) ]


{} -- Record []
reference : a -> FQName -> Value a

A reference that refers to a function or a value with its fully-qualified name.

List.map -- Reference ( [ ..., [ [ "list" ] ], [ "map" ] )
tuple : a -> List (Value a) -> Value a

A tuple represents an ordered list of values where each value can be of a different type.

Note: Tuples with zero values are considered to be the special value Unit

( 1, True ) -- Tuple [ Literal (IntLiteral 1), Literal (BoolLiteral True) ]


( "foo", True, 3 ) -- Tuple [ Literal (StringLiteral "foo"), Literal (BoolLiteral True), Literal (IntLiteral 3) ]


() -- Unit
variable : a -> Name -> Value a

A variable represents a reference to a named value in the scope.

a -- Variable [ "a" ]


fooBar15 -- Variable [ "foo", "bar", "15" ]
ifThenElse : a -> Value a -> Value a -> Value a -> Value a

Represents and if/then/else expression.

if a then
    b
else
    c
-- IfThenElse (Variable ["a"])
--     (Variable ["b"])
--     (Variable ["c"])
patternMatch : a -> Value a -> List ( Pattern a, Value a ) -> Value a

Represents a pattern-match.

case a of
    1 ->
        "yea"


    _ ->
        "nay"
-- PatternMatch (Variable ["a"])
--     [ ( LiteralPattern (IntLiteral 1), Literal (StringLiteral "yea") )
--     , ( WildcardPattern, Literal (StringLiteral "nay") )
--     ]
update : a -> Value a -> List ( Name, Value a ) -> Value a

Update one or many fields of a record value.

{ a | foo = 1 } -- Update (Variable ["a"]) [ ( ["foo"], Literal (IntLiteral 1) ) ]
unit : a -> Value a

Represents the unit value.

() -- Unit
mapValueAttributes : (a -> b) -> Value a -> Value b

Pattern

Patterns are used in multiple ways in the IR: they can take apart a structured value into smaller pieces (destructure) and they can also filter values. The combination of these two features creates a very powerful method tool that can be used in two ways: destructuring and pattern-matching. Pattern-matching is a combination of destructuring, filtering and branching.

type Pattern a
= WildcardPattern a
| AsPattern a (Pattern a) Name
| TuplePattern a (List (Pattern a))
| RecordPattern a (List Name)
| ConstructorPattern a FQName (List (Pattern a))
| EmptyListPattern a
| HeadTailPattern a (Pattern a) (Pattern a)
| LiteralPattern a Literal
| UnitPattern a

Type that represents a pattern.

Matches any value and ignores it (assigns no variable name).

_ -- WildcardPattern
asPattern : a -> Pattern a -> Name -> Pattern a

Assigns a variable name to a pattern.

_ as foo -- AsPattern WildcardPattern ["foo"]


foo -- AsPattern WildcardPattern ["foo"]


[] as foo -- AsPattern EmptyListPattern ["foo"]
tuplePattern : a -> List (Pattern a) -> Pattern a

Destructures a tuple using a pattern for every element.

( _, foo ) -- TuplePattern [ WildcardPattern, AsPattern WildcardPattern ["foo"] ]
recordPattern : a -> List Name -> Pattern a

Pulls out the values of some fields from a record value.

{ foo, bar } -- RecordPattern [ ["foo"], ["bar"] ]
constructorPattern : a -> FQName -> List (Pattern a) -> Pattern a

Matches on a custom type's constructor.

Note: When the custom type has a single constructor this can be used for destructuring. When there are multiple constructors it also does filtering so it cannot be used in a LetDestruct but it can be used in a pattern-match.

Just _ -- ConstructorPattern ( ..., [["maybe"]], ["just"]) [ WildcardPattern ]

Matches an empty list. Can be used standalon but frequently used as a terminal pattern in a HeadTailPattern.

[] -- EmptyListPattern


[ _ ]
-- HeadTailPattern
--     WildcardPattern
--     EmptyListPattern

Matches the head and the tail of a list. It can be used to match lists of at least N items by nesting this pattern N times and terminating with EmptyListPattern.

[ a ]
-- HeadTailPattern
--     (AsPattern WildcardPattern ["a"])
--     EmptyListPattern


a :: b
-- HeadTailPattern
--     (AsPattern WildcardPattern ["a"])
--     (AsPattern WildcardPattern ["b"])


[ a, b ]
-- HeadTailPattern
--     (AsPattern WildcardPattern ["a"])
--     (HeadTailPattern
--         (AsPattern WildcardPattern ["b"])
--         EmptyListPattern
--     )
literalPattern : a -> Literal -> Pattern a

Matches a specific literal value. This pattern can only be used in a pattern-match since it always filters.

True -- LiteralPattern (BoolLiteral True)


'a' -- LiteralPattern (CharLiteral 'a')


"foo" -- LiteralPattern (StringLiteral "foo")


13 -- LiteralPattern (IntLiteral 13)


15.4 -- LiteralPattern (FloatLiteral 15.4)

Specification

The specification of what the value or function is without the actual data or logic behind it.

type alias Specification a =
{ inputs : List ( Name, Type a )
, output : Type a
}

Type that represents a value or function specification. The specification of what the value or function is without the actual data or logic behind it.

mapSpecificationAttributes : (a -> b) -> Specification a -> Specification b

Definition

A definition is the actual data or logic as opposed to a specification which is just the specification of those. Value definitions can be typed or untyped. Exposed values have to be typed.

type alias Definition a =
{ valueType : Maybe (Type a)
, arguments : List ( Name, a )
, body : Value a
}

Type that represents a value or function definition. A definition is the actual data or logic as opposed to a specification which is just the specification of those. Value definitions can be typed or untyped. Exposed values have to be typed.

typedDefinition : Type a -> List ( Name, a ) -> Value a -> Definition a

Typed value or function definition.

Note: Elm uses patterns instead of argument names which is flexible but makes it more difficult to understand the model. Since most business models will actually use names which is represented as AsPattern WildcardPattern name in the IR we will extract those into the definition. This is a best-efforts process and stops when it runs into a more complex pattern. When that happens the rest of the argument patterns will be pushed down to the body as lambda arguments. The examples below try to visualize the process.

myFun : Int -> Int -> { foo : Int } -> Int
myFun a b { foo } =
    body


-- the above is logically translated to the below
myFun :
    Int
    -> Int
    -> { foo : Int }
    -> Int -- the value type does not change in the process
myFun a b =
    \{ foo } ->
        body
untypedDefinition : List ( Name, a ) -> Value a -> Definition a

Untyped value or function definition.

Note: Elm uses patterns instead of argument names which is flexible but makes it more difficult to understand the model. Since most business models will actually use names which is represented as AsPattern WildcardPattern name in the IR we will extract those into the definition. This is a best-efforts process and stops when it runs into a more complex pattern. When that happens the rest of the argument patterns will be pushed down to the body as lambda arguments. The examples below try to visualize the process.

myFun a b { foo } =
    body


-- the above is logically translated to the below
myFun a b =
    \{ foo } ->
        body
(Type a -> Result e (Type a))
-> (Value a -> Result e (Value a))
-> Definition a
-> Result (List e) (Definition a)
mapDefinitionAttributes : (a -> b) -> Definition a -> Definition b