Учебник по Haskell | страница 64



(p - a) * (p - b) * (p - c))

Слова let и in – ключевые. Выгодным отличием let-выражений является то, что они являются обычными

выражениями и не привязаны к определённому месту как where-выражения. Они могут участвовать в любой

части обычного выражения:

square a b c = let p = (a + b + c) / 2

in

sqrt ((let pa = p - a in p * pa) *

(let pb = p - b

pc = p - c

in

pb * pc))

В этом проявляется их принадлежность композиционному стилю. let-выражения могут участвовать в

любом подвыражении, они также группируются скобками. А where-выражения привязаны к уравнениям в

определении функции.

Также как и в where-выражениях, в let-выражениях слева от знака равно можно проводить декомпозицию

значений.

pred :: Nat -> Nat

pred x = let (Succ y) = x

in

y

Определим функцию фильтрации списков через let:

filter :: (a -> Bool) -> [a] -> [a]

filter

p

[]

= []

filter

p

(x:xs) =

let rest = filter p xs

in

if p x then x : rest else rest

4.2 Декомпозиция

Декомпозиция или сопоставление с образцом позволяет выделять из составных значений, простейшие

значения с помощью которых они были построены

pred (Succ x) = x

и организовывать условные вычисления которые зависят от вида поступающих на вход функции значений

not True

= False

not False = True

Сопоставление с образцом

Декомпозицию в декларативном стиле мы уже изучили, это обычный случай разбора значений в аргу-

ментах функции. Рассмотрим одну полезную возможность при декомпозиции. Иногда нам хочется провести

декомпозицию и дать псевдоним всему значению. Это можно сделать с помощью специального символа @.

Например определим функцию, которая возвращает соседние числа для данного числа Пеано:

beside :: Nat -> (Nat, Nat)

beside

Zero

= error ”undefined”

beside

x@(Succ y) = (y, Succ x)

В выражении x“(Succ y)@ мы одновременно проводим разбор и даём имя всему значению.

Декомпозиция | 61

case-выражения

Оказывается декомпозицию можно проводить в любом выражении, для этого существуют case-

выражения:

data AnotherNat = None | One | Two | Many

deriving (Show, Eq)

toAnother :: Nat -> AnotherNat

toAnother x =

case x of

Zero

-> None

Succ Zero

-> One

Succ (Succ Zero)

-> Two

_

-> Many

fromAnother :: AnotherNat -> Nat

fromAnother None

= Zero

fromAnother One

= Succ Zero

fromAnother Two

= Succ (Succ Zero)

fromAnother Many

= error ”undefined”

Слова case и of – ключевые. Выгодным отличием case-выражений является то, что нам не приходит-

ся каждый раз выписывать имя функции. Обратите внимание на то, что в case-выражениях также можно

пользоваться обычными переменными и безымянными переменными.