Se então, senão

Você saberia calcular o maior de dois números \(a\) e \(b\) sem usar um teste do tipo se então senão? É bem interessante; assuma \(M\) maior e \(m\) menor entre \(a\) e \(b\).

\[\begin{eqnarray} M &=& \frac{M + M}{2} \nonumber \\ &=& \frac{M + m + M - m}{2} \nonumber \\ &=& \frac{M + m + (M-m)}{2} \nonumber \\ &=& \frac{M + n + \|M-m\|}{2} \nonumber \\ &=& \frac{a + b + \|a - b\|}{2} \nonumber \\ &=& \frac{a + b}{2} + \frac{\|a - b\|}{2} \nonumber \\ \end{eqnarray}\]

Em outras palavras, o maior entre dois números \(a\) e \(b\) é igual à média dos números \(a\) e \(b\), mais a metade da diferença entre \(a\) e \(b\). Logo, em Haskell, temos

maior x y = (x + y + (abs (x - y))) / 2

Estou certo de que você concordará que calcular o maior entre dois números deveria ser muito mais simples que isso, especialmente porquê naquele abs provavelmente há um se-então-senão escondido.

\[ abs(a,b)= \begin{cases} a,& \text{if } a\geq b\\ b, & \text{otherwise} \end{cases} \]

Mas como fazê-lo em Haskell, isto é, como testar uma condição sobre os valores para decidir a forma correta de computar o resultado? Usando uma expressão de seleção, isto é, if ... then ... else ... Esta estrutura tem a seguinte sintaxe, em que a definição True é usada caso a condição avalie para True e condição False é usada caso contrário.

if <condição> then <definição True> else <definição False>

Por exemplo, veja podemos calcular o maior de dois números com a seguinte definição.

maior x y = if x > y then x
                     else y

Observe que, diferentemente de outras linguagens em que se pode usar o if para decidir entre fazer ou não uma computação, o if do Haskell serve para decidir entre duas computações. Isto é, o if deve sempre ser seguido do then e do else.

Observe também que o if pode estar em qualquer parte da expressão, porquê este construto é também uma expressão. Por exemplo, imagine que queira somar um número inteiro com o valor absoluto de outro número, sem usar o abs.

somaEstranha x y = x + (if y < 0 then -y else y)

Com esta definição, tanto somaEstranha 1 2 quanto somaEstranha 1 (-2) resultam em 3. Mas este exemplo é muito estranho, então pensemos em um mais "útil", como determinar se um ano é bissexto.

  • Se o ano não é múltiplo de 4, não é bissexto.
  • Se é múltiplo de 4 e não é múltiplo de 100, então é bissexto.
  • Se é múltiplo de 100 e não é múltiplo de 400, então não é bissexto.
  • Se é múltiplo de 400, então é bissexto.
bissexto x = if mod x 4 /= 0 
                then False
                else if mod x 100 /= 0 
                    then True
                    else if mod x 400 == 0 
                        then True
                        else False

Aninhar if assim pode funcionar, mas leva a estruturas complexas e difíceis de serem lidas. Há formas melhores de se lidar com múltiplas possibilidades de computação, como veremos adiante.