I think case of
is quite straight forward, as i come from more imperative languages.
Nevertheless, i have encountered a Kata where one of the solutions by another user, confuses me about the use of case and Data.List (sort)
import Data.List (sort)
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c =
case sort [a,b,c] of
[min, middle, max] -> (min middle) > max
By definition, 3 segments can make a triangle if the condition a b > c
is met for the 3 permutations of [a,b,c] so, something more straight forward (my answer) would be:
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c = a b > c && b c > a && a c > b
My question is, in the case above, how is the case of
testing that condition for the 3 combinations?
CodePudding user response:
Imagine that a b and c are ordered from small to large, then the algorithm tests that a b > c, which is what the first implementation checks.
If we know that a < b < c, and a b > c holds, then we know that a c > b holds. Indeed: a c > a b > c > b, hence a c > b holds because a b > c holds. Furthermore b c > a b > c > a holds, and thus b c > a holds as well.
This thus means that checking if it holds for a known minimum, maximum and value in between, the two other equations are implied.
What the case … of
does here is sorting the list [a, b, c]
and unpacking the sorted list in min
, middle
and max
, it is thus a tool that is used to assign the smallest value to min
, the largest value to max
and the remaining value to middle
. A where …
or let … in …
is probably more elegant, for example:
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c = (min middle) > max
where [min, middle, max] = sort [a, b, c]