Build a file!
Elm.file [ "My", "Module" ]
[ Elm.declaration "placeholder"
(Elm.string "a fancy string!")
]See what code this expression would generate!
Note - Check out the Elm.ToString module if this doesn't quite meet your needs!
Sometimes you may need to add a manual type annotation.
import Elm.Annotation as Type
Elm.value
{ importFrom = []
, name = "myString"
, annotation = Nothing
}
|> Elm.withType Type.stringThough be sure elm-codegen isn't already doing this automatically for you!
Elm.record
[ ( "name", Elm.string "Elm" )
, ( "designation", Elm.string "Pretty fabulous" )
]record
|> Elm.get "field"results in
record.fieldmyRecord
|> updateRecord
[ ( "designation", Elm.string "Pretty fabulous" )
]Results in
{ myRecord | designation = "Pretty fabulous" }ifThen (Elm.bool True)
(Elm.string "yes")
(Elm.string "no")Will generate
if True then
"yes"
else
"no"If you need more than one branch, then chain them together!
Elm.ifThen (Elm.bool True)
(Elm.string "yes")
(Elm.ifThen (Elm.bool True)
(Elm.string "maybe")
(Elm.string "no")
)Will generate
if True then
"yes"
else if True then
"maybe"
else
"no"Renders a multiline comment.
Elm.comment """Here is my comment!"""Will generate
{- Here is my comment! -}This will include some markdown in the module doc comment.
Add a documentation comment to a declaration!
Group declarations in a module.
This will add a @docs tag to the module doc comment for any exposed functions in the group.
Elm.group
[ myFunction
, myOtherFunction
]Will create the following module doc comment:
@docs myFunction, myOtherFunctionBy default, everything is exposed for your module.
However, you can tag specific declarations you want exposed, and then only those things will be exposed.
Same as file, but you have more control over how the module comment is generated!
Pass in a function that determines how to render a @docs comment.
Each exposed item is grouped using group.
aliases allow you to specify a module alias to be used.
Elm.fileWith [ "MyModule" ]
{ docs = "# Here's my cool module!"
, aliases =
[ ( [ "Json", "Encode" ], "Encode" )
]
}
[-- whatever declarations you desire.
]would make an import statement like
import Json.Encode as EncodeAll values rendered in this file that are from this module would also automatically respect this alias as well.
Create a function with a single argument.
This may seem a little weird the first time you encounter it, so let's break it down.
Here's what's happening for the fn* functions —
String arguments are the names of the arguments for the generated function.Maybe Annotation is the type annotation. If you provide Nothing, then elm-codegen will infer the type for you!(Expression -> Expression) function is where we're providing you an Expression that represents an argument coming in to the generated function.So, this
Elm.fn (Elm.Arg.var "firstInt")
(\firstArgument ->
Elm.Op.plus
(Elm.int 42)
firstArgument
)Generates
\firstInt -> 42 + firstIntIf you want to generate a top level function instead of an anonymous function, use Elm.declaration.
Elm.declaration "add42" <|
Elm.fn (Elm.Arg.var "firstInt")
(\firstArgument ->
Elm.Op.plus
(Elm.int 42)
firstArgument
)Results in
add42 : Int -> Int
add42 firstInt =
42 + firstIntNote — Elm CodeGen will protect variable names if they're used in a nested fn* by adding a string of numbers to the end of the name. So, you may see a variable name be something like myVariable_0_1.
Build a function with any number of arguments.
Here's how you'd implement a function which adds two numbers together:
Elm.fnBuilder
(\arg1 arg2 ->
Elm.Op.plus arg1 arg2
)
|> Elm.fnArg (Elm.Arg.var "arg1")
|> Elm.fnArg (Elm.Arg.var "arg2")
|> Elm.fnDoneCheck out the Elm.Arg module for more information on how to create one of these.
body allows you to define the funciton body after defining the args.
So, normally, we'd have this.
Elm.fnBuilder
(\arg1 arg2 ->
Elm.Op.plus arg1 arg2
)
|> Elm.fnArg (Elm.Arg.var "arg1")
|> Elm.fnArg (Elm.Arg.var "arg2")
|> Elm.fnDoneBut, that's sorta weird because you're defining the body before the args.
You can also do this:
Elm.fnBuilder Tuple.pair
|> Elm.fnArg (Elm.Arg.var "arg1")
|> Elm.fnArg (Elm.Arg.var "arg2")
|> Elm.body
(\( arg1, arg2 ) ->
Elm.Op.plus arg1 arg2
)Which more closely mirrors the way you'd write a function in Elm.
The downside is that you need to capture the arguments in a data strucutre(in this example, we used Tuple.pair).
You may run into situations where you don't know the number of arguments for a function at compile-time.
In that case you can use function. It follows the same pattern as the fn* functions.
Provide it with —
Expressions.This is a special case of function declaration which will reduce itself if possible.
Meaning, if this would generate the following code
\myArg -> someOtherFunction myArgThen it will replace itself with just
someOtherFunctionNote you likely won't need this! It's generally used by the package-helper generator, but that might be a relatively special case.
A custom type declaration.
Elm.customType "MyType"
[ Elm.variant "One"
, Elm.variantWith "Two"
[ Elm.Annotation.list Elm.Annotation.string ]
]Will result in
type MyType
= One
| Two (List String)A custom type declaration, with the ability to specify in which order to put the type variables.
Elm.customTypeWith "MyType"
[ "addVar", "twoVar" ]
[ Elm.variantWith "One"
[ Elm.Annotation.var "oneVar" ]
, Elm.variantWith "Two"
[ Elm.Annotation.var "twoVar" ]
]Will result in
type MyType addVar twoVar oneVar
= One oneVar
| Two twoVarNotice how nonexisting variables (as used in phantom types) are included, and missing variable are automatically added.
A type alias declaration.
import Elm.Annotation as Type
Elm.alias "MyAlias"
(Type.record
[ ( "one", Type.string )
, ( "two", Type.int )
, ( "three", Type.var "content" )
]
)Should result in
type alias MyAlias content =
{ one : String
, two : Int
, three : content
}A type alias declaration, with the ability to specify in which order to put the type variables.
import Elm.Annotation as Type
Elm.aliasWith "MyAlias" [ "twoVar", "nonexistingVar", "oneVar" ]
(Type.record
[ ( "one", Type.var "oneVar" )
, ( "two", Type.var "twoVar" )
, ( "three", Type.var "threeVar" )
]
)Should result in
type alias MyAlias twoVar oneVar threeVar =
{ one : oneVar
, two : twoVar
, three : threeVar
}Notice how nonexisting variables are omitted, and missing variable are automatically added.
import Elm.Annotation as Type
Elm.portIncoming "receiveMessageFromTheWorld" Type.intResults in
port receiveMessageFromTheWorld :
(Int -> msg)
-> Sub msgNote You generally only need one incoming and one outgoing port!
If you want to vary the messages going in and out of your app, don't use a huge number of ports, instead write Json encoders and decoders.
This will give you more flexibility in the future and save you having to wire up a bunch of stuff.
Another note - You may need to expose your port explicitly using Elm.expose.
Create a port that can send messages to the outside world!
import Elm.Annotation as Type
Elm.portOutgoing "tellTheWorld" Type.stringwill generate
port tellTheWorld : String -> Cmd msgThis will insert the given string into your generated file.
Check out the using packages/helpers guide. If you're reaching for this, it's likely you'd be better off using a local helper file!
Unwraps a single-variant type
Elm.declaration "myFunction" <|
Elm.fn "val"
(\val ->
Elm.unwrap "MyType" val
)Results in the following lambda
myFunction val =
(\(MyType val) -> val) valGenerate a lambda which unwraps a single-variant type.
Elm.unwrapper [ "MyModule" ] "MyType"Results in the following lambda
\(MyModule.MyType val) -> val