Are there partial functions in DAML?

In Scala you the concept of partial functions. These are useful for instance in collect function on collections, e.g.:

1 to 10 collect {
  case x if x % 2 == 0 => x.toString
}

While it is recommended to avoid partial functions, under some circumstances they might be useful. I was wondering if this would be (or is?) possible in DAML? Something like the pseudo code:

collect [1..10] (case x | x % 2 == 0 -> show x) -- ["2", "4", "6", "8", "10"]
1 Like

There is no builtin concept of partial functions like there is in Scala. Functions with incomplete pattern matches or calls to error are called partial functions but contrary to Scala you cannot handle the error case so they behave quite differently.

If you want something similar to a partial function in Scala, change the return type of your function to Optional a. You can then use mapOptional as the equivalent of collect. Putting things together, your example can be rewritten as follows:

evenToText : Int -> Optional Text
evenToText x
  | x % 2 == 0 = Some (show x)
  | otherwise = None
evenTexts : [Text]
evenTexts = mapOptional evenToText [1..10]                 
1 Like

Thanks, that seems like a viable option.

Will using Optional cause heap allocations at runtime? Or are these actually modelled as value types?

1 Like

It does involve a heap allocation atm but I would be surprised if that becomes the bottleneck atm. In general, there are a ton of heap allocations in the interpreter atm and trying to optimize allocations in your DAML code is mostly not a useful optimization at this point.

1 Like

Thanks, I was just curious whether we are closer the JVM than to Haskell in this particular case. (I assume the Maybe is a value type in Haskell.)

1 Like

In Haskell Just also has a pointer to the value rather than the value itself. You can unpack fields in Haskell but only if they are not polymorphic.

1 Like

Another option here would be to use list comprehension notation:

module Main where

setup = scenario do
  let evensAsText = [show x | x <- [1..10], x % 2 == 0]
  debug evensAsText
2 Likes