finos / morphir-elm / Morphir.Value.Native

This module contains an API and some tools to implement native functions. Native functions are functions that are not expressed in terms Morphir expressions either because they cannot be or they are more efficient natively. Native in this context means evaluating within Elm which in turn translates to JavaScript which either executes in the browser or on the backend using Node.

Native functions are mainly used in the interpreter for evaluating SDK functions. Think of simple things like adding two numbers: the IR captures the fact that you want to add them in a reference Morphir.SDK.Basics.add and the interpreter finds the native function that actually adds the two numbers (which would be impossible to express in Morphir since it's a primitive operation).


type alias Function =
Eval -> List Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

Type that represents a native function. It's a function that takes two arguments:

Lazy evaluation

One important thing to understand is that the API allows lazy evaluation. Instead of evaluating arguments before they are passed to the native function they are passed without evaluation. This allows the native function itself to decide what order to evaluate arguments in. Think of the boolean and and or operators, they can often skip evaluation of the second argument depending on the value of the first argument.

Also, when a lambda is passed as an argument it might need to be evaluated multiple times with different inputs. For example the predicate in a filter will need to be evaluated on each item in the list.


type alias Eval =
Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

Type that captures a function used for evaluation. This will usually backed by the interpreter.

Utilities

Various utilities to help with implementing native functions.

unaryLazy : (Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Function

Create a native function that takes exactly one argument. Let the implementor decide when to evaluate the argument.

nativeFunction : Native.Function
nativeFunction =
    unaryLazy
        (\eval arg ->
            eval arg
                |> Result.map
                    (\evaluatedArg ->
                        -- do something
                    )
        )

unaryStrict : (Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Function

Create a native function that takes exactly one argument. Evaluate the argument before passing it to the supplied function.

nativeFunction : Native.Function
nativeFunction =
    unaryLazy
        (\eval evaluatedArg ->
            -- do something with evaluatedArg
        )

binaryLazy : (Eval -> Morphir.IR.Value.RawValue -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Function

Create a native function that takes exactly two arguments. Let the implementor decide when to evaluate the arguments.

nativeFunction : Native.Function
nativeFunction =
    binaryLazy
        (\eval arg1 arg2 ->
            eval arg1
                |> Result.andThen
                    (\evaluatedArg1 ->
                        eval arg2
                            |> Result.andThen
                                (\evaluatedArg2 ->
                                    -- do something with evaluatedArg1 and evaluatedArg2
                                )
                    )
        )

binaryStrict : (Morphir.IR.Value.RawValue -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Function

Create a native function that takes exactly two arguments. Evaluate both arguments before passing then to the supplied function.

nativeFunction : Native.Function
nativeFunction =
    binaryStrict
        (\eval evaluatedArg1 evaluatedArg2 ->
            -- do something with evaluatedArg1 and evaluatedArg2
        )

boolLiteral : Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error Basics.Bool

charLiteral : Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error Char

eval0 : r -> Encode r -> Function

eval1 : (a -> r) -> Decoder a -> Encode r -> Eval -> List Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

eval2 : (a -> b -> r) -> Decoder a -> Decoder b -> Encode r -> Eval -> List Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

eval3 : (a -> b -> c -> r) -> Decoder a -> Decoder b -> Decoder c -> Encode r -> Eval -> List Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

floatLiteral : Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error Basics.Float

intLiteral : Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error Basics.Int

oneOf : List Function -> Function

stringLiteral : Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error String

decimalLiteral : Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error Morphir.SDK.Decimal.Decimal

decodeFun1 : Encode a -> Decoder r -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error (a -> Result Morphir.Value.Error.Error r)

decodeList : Decoder a -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error (List a)

decodeLiteral : (Morphir.IR.Literal.Literal -> Result Morphir.Value.Error.Error a) -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error a

decodeMaybe : Decoder a -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error (Maybe a)

decodeLocalDate : Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.SDK.LocalDate.LocalDate

decodeRaw : Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

decodeTuple2 : ( Decoder a, Decoder b ) -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error ( a, b )

encodeList : Encode a -> List a -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeLiteral : (a -> Morphir.IR.Literal.Literal) -> a -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeMaybe : Encode a -> Maybe a -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeLocalDate : Morphir.SDK.LocalDate.LocalDate -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeMaybeResult : Maybe (Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeRaw : Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeResultList : List (Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

encodeTuple2 : ( Encode a, Encode b ) -> ( a, b ) -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

decodeDict : Decoder k -> Decoder v -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error (Morphir.SDK.Dict.Dict k v)

decodeFun2 : Encode a -> Encode b -> Decoder r -> Eval -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error (a -> b -> Result Morphir.Value.Error.Error r)

encodeDict : Encode k -> Encode v -> Morphir.SDK.Dict.Dict k v -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue

trinaryLazy : (Eval -> Morphir.IR.Value.RawValue -> Morphir.IR.Value.RawValue -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Function

trinaryStrict : (Morphir.IR.Value.RawValue -> Morphir.IR.Value.RawValue -> Morphir.IR.Value.RawValue -> Result Morphir.Value.Error.Error Morphir.IR.Value.RawValue) -> Function