# How to use Either in Guard statement

Hi Everyone

I am new here and this is my first post. I am learning DAML and in the middle of one of the course videos.

I am trying to figure out how to chain together Functions returning Either Right or Left and if that is right I am trying to chain together conditional statements. I know how to do this in Rust for example but any help how to do this in DAML would be much appreciated. And how do I save into variables the result of the either statement if that the type is Right. Thank you

Maybe my thought process is not functional enough. Thank you for all your help!

Here is the code that I cannot seem to make to work. If you decide to help please keep it basic for me thank you

â€“ either
checkNumberOfSides: [Decimal] â†’ Either Text [Decimal]
checkNumberOfSides sides =
if ((length sides) /= 3) then
Left â€śErrorâ€ť
else Right sides

checkIfSideIsZero: [Decimal] â†’ Int â†’ Either Text [Decimal]
checkIfSideIsZero sides idx =
if (head sides == 0.0) then
Left â€śErrorâ€ť
else Right (tail sides)

triangleArea: [Decimal] â†’ Either Text [Decimal]
triangleArea sides =
if (checkNumberOfSides sides) then
if (checkIfSideIsZero 1) then
if (checkIfSideIsZero 2) then
if (checkIfSideIsZero 3) then
??

ideally I would like to do this

| â€¦
| â€¦
| â€¦

So the primary issue here is that guards need to be Boolean expression, i.e. they need to return a Boolean value, not an `Either a b`.

You have two options: either you transform your functions into predicate, or you use `Either a b` as a monad. The shortest way to get your code to â€śworkâ€ť as a monad would be something like:

``````module Main where

import Daml.Script
import DA.Math (sqrt)

checkNumberOfSides: [Decimal] -> Either Text [Decimal]
checkNumberOfSides sides =
if ((length sides) /= 3) then
Left "Error"
else Right sides

checkIfSideIsZero: [Decimal] -> Int -> Either Text [Decimal]
checkIfSideIsZero sides idx =
if (head sides == 0.0) then
Left "Error"
else Right (tail sides)

{-
-- This doesn't work, because guards must be Boolean expressions.
triangleAreaWrong: [Decimal] -> Either Text [Decimal]
triangleAreaWrong sides = case sides of
_ | checkNumberOfSides sides -> Right sides
_ | checkIfSideIsZero sides 1 -> Right sides
_ | checkIfSideIsZero sides 2 -> Right sides
_ | checkIfSideIsZero sides 3 -> Right sides
_ -> Left "Error"
-}

triangleArea: [Decimal] -> Either Text Decimal
triangleArea sides = do
[a, b, c] <- checkNumberOfSides sides
_ <- checkIfSideIsZero sides 1
_ <- checkIfSideIsZero sides 2
_ <- checkIfSideIsZero sides 3
let s = (sum sides) / 2.0
return \$ sqrt (s * (s -a) * (s - b) * (s -c))

setup : Script ()
setup = script do
debug \$ triangleArea [1.0, 1.0, 1.0]
return ()
``````

But thatâ€™s not very satisfying with all those `_ <-`. We can do better. First, hereâ€™s what the guard-based approach could look like:

``````module Main where

import Daml.Script
import DA.Math (sqrt)

hasThreeSides: [Decimal] -> Bool
hasThreeSides sides = length sides == 3

noZeroSide: [Decimal] -> Bool
noZeroSide sides = 0.0 `notElem` sides

triangleArea: [Decimal] -> Either Text Decimal
triangleArea sides = case sides of
[a, b, c] | hasThreeSides sides && noZeroSide sides ->
let s = (sum sides) / 2.0
in return \$ sqrt (s * (s -a) * (s - b) * (s -c))
_ -> Left "Error"

setup : Script ()
setup = script do
debug \$ triangleArea [1.0, 1.0, 1.0]
return ()
``````

Itâ€™s not clear to me what using guards and `Either a b` adds in this case, but I think this illustrates nicely that this would not work as you want it to: you want to check that all the conditions match, whereas the guard syntax would offer one branch per condition.
If you want an example of how this could be constructed with `Either a b`, we could try something like this:

``````module Main where

import Daml.Script
import DA.List((!!))
import DA.Math (sqrt)

nonZero: Decimal -> Either Text Decimal
nonZero 0.0 = Left "zero element"
nonZero x = Right x

asTriangle: [Decimal] -> Either Text (Decimal, Decimal, Decimal)
asTriangle sides =
if length sides /= 3 then
Left \$ "Incorrect number of sides: " <> show (length sides)
else do
a <- nonZero \$ sides !! 0
b <- nonZero \$ sides !! 1
c <- nonZero \$ sides !! 2
return (a, b, c)

triangleArea: [Decimal] -> Either Text Decimal
triangleArea sides = do
(a, b, c) <- asTriangle sides
let s = (sum sides) / 2.0
return \$ sqrt (s * (s -a) * (s - b) * (s -c))

hasThreeSides: [Decimal] -> Bool
hasThreeSides sides = length sides == 3

noZeroSide: [Decimal] -> Bool
noZeroSide sides = 0.0 `notElem` sides

setup : Script ()
setup = script do
debug \$ triangleArea [1.0, 1.0, 1.0]
return ()
``````

Hopefully this clarifies things a bit. Otherwise, please donâ€™t hesitate to ask more questions.

2 Likes

Thank you for your valuable input Gary.

And that kicks off my journey in DAML.

Brilliant. Thank you for the time and effort. Clears up a lot.