Why is there no `for` in daml?

DAML seems to have a forA corresponding to a mapA. Just for the sake of completeness, why is there no for corresponding to a map?

3 Likes

This is primarily due to being based on Haskell. Haskell has a for function but it is actually equivalent to forA in DAML. So to avoid any potential confusion, we did not add a for to DAML. That said, I don’t think it would be that unreasonable to add it.

3 Likes

Be aware that map is specialised to list, and as such we generally prefer to use fmap which is the same function generalised over all Functor’s from which map is derived. This contrasts with mapA which is already generalised over Applicative and Traversable*.

Moreover when we use fmap (over [], Optional, NonEmpty, Update, or some other Functor), we generally use the operator version <$>. So instead of writing fmap someFunction someList we write somefunction <$> someFunctor. This is generally easier to read, especially as operator precedence often allows us to eliminate multiple parentheses by using an operator like this**.

There are occasions where the code is easier to read if we swap the function and the list arguments — fortunately, while there is no for function in the standard library, there is a for operator <&>. So you can always write someFunctor <&> someFunction.

In short, you will almost always find your code easier to read and write if you use <$> in preference to fmap and occasionally <&> where you want the arguments flipped.

  • In fact in much the same way the existence of a lawful fmap is what defines a Functor, the existence of a lawful mapA is what defines a Traversable.

** The two common exceptions to this are:

  1. Where you want to partially apply fmap to define a function. ie.
f : Update Text -> Update Int
f = fmap length
  1. Where you need to fmap over nested functors, ie. applying f : (a -> b) to arg : [Optional a] to get [Optional b]. So we do find a few places in our code where we write fmap f <$> arg.

A quick grep indicates 1805 uses of <$>, 241 uses of <&>, 267 uses of fmap (the vast majority of which fall into case 1 above).

PS. As an aside, as you move from introductory to intermediate DAML, it is highly recommended that you take the time to explore and understand the core typeclasses Functor, Applicative, Action, and Traversable, their functions, operators, and hierarchy, as advanced DAML techniques often assume a familiarity with these concepts, and they do allow you to simplify otherwise quite complicated DAML code.

2 Likes