The following does not compile. Is there a way to pattern match a list that has a head and a non-empty tail?
firstNumber : [Int] -> Text
firstNumber [] = "Empty list!"
firstNumber [x] = "The *only* number is " <> (show x)
firstNumber x::xs = "The *first* number is " <> (show x)
firstNumber (x::y::xs) = "The *first* number is " <> (show x) <> " and second is " <> show y
Interesting, @Leonid_Rozenberg. You are right. The pattern (x::y::xs)
can be used to identify lists with at least two items.
import DA.Assert
firstNumber : [Int] -> Text
firstNumber (x::y::xs) = "The *first* number is " <> (show x)
firstNumber [x] = "The *only* number is " <> (show x)
firstNumber [] = "Empty list!"
testing = script do
"Empty list!" === firstNumber []
"The *only* number is 1" === firstNumber [1]
"The *first* number is 1" === firstNumber [1, 2]
"The *first* number is 1" === firstNumber [1, 2, 3, 4]
I suppose I could use (x::xs)
instead of (x::y::xs)
if the order of the matching filters out single-element lists first:
import DA.Assert
firstNumber : [Int] -> Text
firstNumber [] = "Empty list!"
firstNumber [x] = "The *only* number is " <> (show x)
firstNumber (x::xs) = "The *first* number is " <> (show x)
testing = script do
"Empty list!" === firstNumber []
"The *only* number is 1" === firstNumber [1]
"The *first* number is 1" === firstNumber [1, 2]
"The *first* number is 1" === firstNumber [1, 2, 3, 4]
But, I see (x::y::xs)
captures the intent without requiring the context of the surrounding pattern matching statements. Nice!
Being able to write precise pattern matches to express logic (ex, a list with at least 2 elements) is one of the unacknowledged strengths of functional programming languages.