{{ message }}

Instantly share code, notes, and snippets.

# choonkeat/destructuring-phantom-type-appendix.md

Last active Feb 18, 2020

A note about "type signature" and "type variables"

`convert : Exchange from to -> Currency from -> Currency to`

`from` and `to` are type variables to ensure things line up.

They are not variables in the regular sense: we cannot use `from` or `to` in our function body to `+` or do anything with. Actually, in our function body, there is no variable `from` or `to`

```convert : Exchange from to -> Currency from -> Currency to
convert arg1 arg2 =
-- FYI you can use variable `arg1` or `arg2`
-- BUT there are no variables `from` or `to` for use here```

While reading https://thoughtbot.com/blog/modeling-currency-in-elm-using-phantom-types#constraint-2-conversions there's a problem understanding the type signature of

```convert : Exchange from to -> Currency from -> Currency to
convert (Exchange rate) (Currency c) =
Currency <| round (rate * toFloat c)```

I [mentally] map `Exchange from to` in first line to `Exchange rate` in second line. Then I am lost how do I get the `rate` and where do `from to` go? Could someone give suggestion on how to understand this?

Rewriting the code a bit, I think this type signature won't be confusing:

```convert : Exchange from to -> Currency from -> Currency to
convert exchangeFromTo currencyFrom =```

So the first argument `exchangeFromTo` argument variable is type `Exchange from to` (and `currencyFrom` second argument is type `Currency from`)

Now to work with `exchangeFromTo`, we need to pattern match / destructure it to get the `Float` value we want out of it. To know what patterns are available to match with in a Custom Type, we can look at the type definition:

```type Exchange from to
= Exchange Float -- this is our only constructor, `Exchange blah` where `blah` will be a `Float` value```

and we can use it like this

```convert : Exchange from to -> Currency from -> Currency to
convert exchangeFromTo currencyFrom =
case exchangeFromTo of
Exchange rate ->
-- do stuff with variable `rate` which is a `Float````

When there's only 1 pattern, we can also write it in this way (see here for more examples)

```convert : Exchange from to -> Currency from -> Currency to
convert exchangeFromTo currencyFrom =
let
(Exchange rate) = exchangeFromTo
in
-- at this point, we can use the variable `rate` of `Float` type```

since `(Exchange rate)` is equal to `exchangeFromTo`, we can replace it

```convert : Exchange from to -> Currency from -> Currency to
convert (Exchange rate) currencyFrom =```

So now we've arrived at where you were confused, the first argument being specified as `(Exchange rate)` and the rest of the function using variable `rate` value of `Float` type

### ingemar0720 commented Feb 17, 2020

What if there are more constructor in this example?, e.g. to re-write `type Exchange` to be

``````type Exchange from to
= Exchange Float
= Exchange String String
``````

Shall the implementation also add in one argument?

``````convert : Exchange from to -> Currency from -> Currency to
convert (Exchange rate someInt) currencyFrom =
``````

Or we shall use case of to do pattern match?

``````convert exchangeFromTo  currencyFrom =
case exchangeFromTo of
Exchange rate ->
-- do stuff with variable `rate` which is a `Float`
Exchange rate someInt ->
-- do stuff with variable `rate` which is a `Float` and variable`someInt` which is a `Int`
``````

### choonkeat commented Feb 17, 2020 • edited

in some languages (Haskell, Erlang, Elixir) you can define multiple function bodies to cover all the patterns

```convert (Exchange rate) currencyFrom =
-- do stuff with `rate`

convert (Exchange rate someInt) currencyFrom =
-- do stuff with `rate`, `someInt````

Elm does not allow that, preferring you explicitly express all the variants in one place with the usual `case ... of` in 1 function body

```convert exchangeFromTo currencyFrom =
case exchangeFromTo of
Exchange rate ->
-- ...
Exchange rate someInt ->
-- do stuff with `rate`, `someInt````

The ability to define multiple function bodies for pattern matching is pretty cool and actually very very mathy. For example, here's factorial (one function matches the exact value `0` another function matches anything else as `n`)

```factorial 0 = 1
factorial n = n * factorial (n - 1)```

But I agree with Elm approach for maintainability (don't worry about locating the various functions, missing out on a pattern and making micro decisions on where to put that other function, tracing down the wrong function when another is more matching...)

```factorial n =
case n of
0 -> 1
n -> n * factorial (n - 1)```