Clarify the polymorphic functions example from the cheat-sheet

I am working through The Fast Track to Daml. I could use some help understanding the example given for “Polymorphic functions”:

f : (Show a, Eq a) => a -> Text -> Text

I looked for clarification in the “Generic Functions” section of the Daml Language Reference but that did not help. For example, the Functions page of the Daml Language Reference does not include the => characters.

Am I correct that the above example is a function signature for a function named f? And the generic type is named a? What does the => mean? Is the (Show a, Eq a) a tuple? Could an example that does not use Show and Eq be an equally valid example of a “polymorphic function” or is the (Show a, Eq a) bit important for illustrating the idea?

(By the way, I’m coming from an F# background, not Haskell.)

Hi @WallaceKelly! You are right that this defines the function signature for a function named f and a is the type parameter.

(Show a, Eq a) is a type constraint and restricts the possible choices for the parameter to types that implement the Show and Eq typeclasses which allow to show and compare values of that type. If you are not familiar with those typeclasses the chapter on data types in the Daml intro provides more details.

You can write functions without type constraints, an example of that that you’ve probably encountered before is the map function on lists:

map : (a -> b) -> [a] -> [b]
1 Like

Typeclasses in Daml(/Haskell) are somewhat analoguous to interfaces, but a bit more flexible (they can be added after the fact, and they can cover multiple types).

I think of a typeclass as a set of related functions that act on a set of related types.

Show and Eq are fairly simple typeclasses as they both act on a single type at a time. You can think of the Show typeclass as having a single function:

class Show a where
  show: a -> Text

and you can add the Show typeclass to any existing type by creating a “typeclass instance” for it, which is the Haskell parlance for defining its implementation:

data Color = Orange | Yellow | Green

instance Show Color where
  show c = case c of
    Orange -> "Orange"
    Yellow -> "Yellow"
    Green -> "Green"

Similarly, the Eq typeclass can be thought of as having two functions:

class Eq a where
  (==): a -> a -> Bool
  (/=): a -> a -> Bool
  (/=) a b = not (a == b)

which defines the types of the two functions, and defines /= in terms of == so that when you implement an instance for that class you only need to provide ==:

instance Eq Color where
  (==) a b = case (a, b) of
    (Orange, Orange) -> True
    (Yellow, Yellow) -> True
    (Green, Green) -> True
    _ -> False

Now, let’s say we have a Fruit type defined as:

data Fruit = FruitOrange | FruitApple | FruitCherry

instance Show Fruit where
  show f = case f of
    FruitOrange -> "Orange"
    FruitApple -> "Apple"
    FruitCherry -> "Cherry"

You could imagine a situation where you want to make a function that compares the textual representation of these types:

textEq: (Show a, Show b) => a -> b -> Bool
textEq a b = show a == show b

This function can only work if both of its arguments, which may or may not be of the same type, have a Show instance, which is expressed by the part before the => in the signature.

Or if you want an example of two constraints on the same type, as in the cheatsheet:

sayEq: (Show a, Eq a) => a -> a -> Text
sayEq a b = if a == b
  then show a <> " is equal to " <> show b
  else show a <> " is not equal to " <> show b

I can’t really come up with a use-case for the specific signature given in the cheatsheet, though: what can you do with Eq on a single element? :thinking:

1 Like

Doh! A type constraint. I could have figured that out. Thanks, @cocreature!

Thank you, @Gary_Verhaegen for the full and clear explanation of the Show and Eq typeclasses!