InDocumentation Index
Fetch the complete documentation index at: https://docs.canton.network/llms.txt
Use this file to discover all available pages before exploring further.
data and functional-101 you learned how to define your own data types and functions. However, you don’t have to implement everything from scratch. Daml comes with the Daml standard library, which contains types, functions, and typeclasses that cover a large range of use cases.
In this chapter, you’ll get an overview of the essentials and learn how to browse and search the library to find functions. Being proficient with the standard library will make you considerably more efficient writing Daml code. Specifically, this chapter covers:
- The Prelude
- Important types from the standard library, and associated functions and typeclasses
- Typeclasses
- Important typeclasses like
Functor,Foldable, andTraversable - How to search the standard library
haskell-connection covers them in much greater detail. The standard library typeclasses like Applicative, Foldable, Traversable, Action (called Monad in Haskell), and many more, are the bread and butter of Haskell programmers.
There is a project template
daml-intro-11 for this chapter, but it only contains a single source file with the code snippets embedded in this section.The Prelude
You’ve already used a lot of functions, types, and typeclasses without importing anything. Functions likecreate, exercise, and (==), types like [], (,), Optional, and typeclasses like Eq, Show, and Ord. These all come from the Prelude. The Prelude is module that gets implicitly imported into every other Daml module and contains both Daml specific machinery as well as the essentials needed to work with the inbuilt types and typeclasses.
Important types from the Prelude
In addition to thenative-types, the Prelude defines a number of common types:
Lists
You’ve already met lists. Lists have two constructors[] and x :: xs, the latter of which is “prepend” in the sense that 1 :: [2] == [1, 2]. In fact [1,2] is just syntactical sugar for 1 :: 2 :: [].
Tuples
In addition to the 2-tuple you have already seen, the Prelude contains definitions for tuples of size up to 15. Tuples allow you to store mixed data in an ad-hoc fashion. Common use-cases are return values from functions consisting of several pieces or passing around data in folds, as you saw infolds. An example of a relatively wide Tuple can be found in the test modules of the exceptions project. Test.Intro.Asset.TradeSetup.tradeSetup returns the allocated parties and active contracts in a long tuple. Test.Intro.Asset.MultiTrade.testMultiTrade puts them back into scope using pattern matching:
(,,,) where the number of commas determines the arity of the tuple. Type and data constructor can be applied with values inside the brackets, or outside, and partial application is possible:
While tuples of great lengths are available, it is often advisable to define custom records with named fields for complex structures or long-lived values. Overuse of tuples can harm code readability.
Optional
TheOptional type represents a value that may be missing. It’s the closest thing Daml has to a “nullable” value. Optional has two constructors: Some, which takes a value, and None, which doesn’t take a value. In many languages one would write code like this:
Either
Either is used in cases where a value should store one of two types. It has two constructors, Left and Right, each of which take a value of one or the other of the two types. One typical use-case of Either is as an extended Optional where Right takes the role of Some and Left the role of None, but with the ability to store an error value. Either Text, for example behaves just like Optional, except that values with constructor Left have a text associated to them.
As with tuples, it’s easy to overuse
Either and harm readability. Consider writing your own more explicit type instead. For example if you were returning South a vs North b using your own type over Either would make your code clearer.Typeclasses
You’ve seen typeclasses in use all the way fromdata. It’s now time to look under the hood.
Typeclasses are declared using the class keyword:
class Eq a => Ord a means “everything that is orderable can also be compared for equality”. And that’s almost all there’s to it.
Important typeclasses from the Prelude
Eq
TheEq typeclass allows values of a type to be compared for (in)-equality. It makes available two function: == and /=. Most data types from the standard library have an instance of Eq. As you already learned in data, you can let the compiler automatically derive instances of Eq for you using the deriving keyword.
Templates always have an Eq instance, and all types stored on a template need to have one.
Ord
TheOrd typeclass allows values of a type to be compared for order. It makes available functions: <, >, <=, and >=. Most of the inbuilt data types have an instance of Ord. Furthermore, types like List and Optional get an instance of Ord if the type they contain has one. You can let the compiler automatically derive instances of Ord for you using the deriving keyword.
Show
Show indicates that a type can be serialized to Text, ie “shown” in a shell. Its key function is show, which takes a value and converts it to Text. All inbuilt data types have an instance for Show and types like List and Optional get an instance if the type they contain has one. It also supports the deriving keyword.
Functor
Functors are the closest thing to “containers” that Daml has. Whenever you see a type with a single type parameter, you are probably looking at aFunctor: [a], Optional a, Either Text a, Update a. Functors are things that can be mapped over and as such, the key function of Functor is fmap, which does generically what the map function does for lists.
Other classic examples of Functors are Sets, Maps, Trees, etc.
Applicative Functor
Applicative Functors are a bit like Actions, which you met inconstraints, except that you can’t use the result of one action as the input to another action. The only important Applicative Functor that isn’t an action in Daml is the Commands type submitted in a submit block in Daml Script. That’s why in order to use do notation in Daml Script, you have to enable the ApplicativeDo language extension.
Action
Actions were already covered inconstraints. One way to think of them is as “recipes” for a value, which need to be “executed to get at that value. Actions are always Functors (and Applicative Functors). The intuition for that is simply that fmap f x is the recipe in x with the extra instruction to apply the pure function f to the result.
The really important Actions in Daml are Update and Script, but there are many others, like [], Optional, and Either a.
Semigroup and Monoid
Semigroups and monoids are about binary operations, but in practice, their important use is forText and [], where they allow concatenation using the {<>} operator.
Additive and Multiplicative
Additive and Multiplicative abstract out arithmetic operations, so that(+), (-), (*), and some other functions can be used uniformly between Decimal and Int.
Important modules in the standard library
For almost all the types and typeclasses presented above, the standard library contains a module:module-da-list-85985for Listsmodule-da-optional-38505forOptionalmodule-da-tuple-81988for Tuplesmodule-da-either-91022forEithermodule-da-functor-63823for Functorsmodule-da-action-7169for Actionsmodule-da-functor-63823andmodule-da-semigroup-27147for Monoids and Semigroupsmodule-da-text-83238for working withTextmodule-da-time-32716for working withTimemodule-da-date-80009for working withDate
Foldable and Traversable. In loops you learned all about folds and their Action equivalents. All the examples there were based on lists, but there are many other possible iterators. This is expressed in two additional typeclasses: module-da-traversable-75075, and module-da-foldable-94882. For more detail on these concepts, please refer to the literature in haskell-connection, or https://wiki.haskell.org/Foldable_and_Traversable.
Search the standard library
Being able to browse the standard library starting fromstdlib-reference-base is a start, and the module naming helps, but it’s not an efficient process for finding out what a function you’ve encountered does, even less so for finding a function that does a thing you need to do.
Daml has its own version of the Hoogle search engine, which offers search both by name and by signature. This function is fully integrated into the search bar on https://docs.digitalasset.com/, but for those wanting a pure standard library search, it’s also available on https://hoogle.daml.com.
Search for functions by name
Say you come across some functions you haven’t seen before, like the ones in theensure clause of the MultiTrade.
not and null do, but try searching those names in the documentation search. Search results from the standard library will show on top. not, for example, gives
Search for functions by signature
The other very common use case for the search is that you have some values that you want to do something with, but don’t know the standard library function you need. On theMultiTrade template we have a list baseAssets, and thanks to your ensure clause we know it’s non-empty. In the original Trade we used baseAsset.owner as the signatory. How do you get the first element of this list to extract the owner without going through the motions of a complete pattern match using case?
The trick is to think about the signature of the function that’s needed, and then to search for that signature. In this case, we want a single distinguished element from a list so the signature should be [a] -> a. If you search for that, you’ll get a whole range of results, but again, standard library results are shown at the top.
Scanning the descriptions, head is the obvious choice, as used in the let of the MultiTrade template.
You may notice that in the search results you also get some hits that don’t mention [] explicitly. For example:
Foldable [a].
Let’s try another search. Suppose you didn’t want the first element, but the one at index n. Remember that (!!) operator from functional-101? There are now two possible signatures we could search for: [a] -> Int -> a and Int -> [a] -> a. Try searching for both. You’ll see that the search returns (!!) in both cases. You don’t have to worry about the order of arguments.