Определение (.)
является ключевым здесь.
Чтобы привести более простой пример:
decode1, decode2 :: Int -> Char
decode1 x = chr . (abs x)
decode2 = chr . abs
Теперь определение (.)
равно f . g = \a -> f (g a)
, поэтому мы можем использовать это в обоих наших определениях:
decode1 x = \a -> chr (abs x a)
decode2 = \x -> chr (abs x)
Мы можем еще больше упростить это, переместив лямбда-параметры в соответствие шаблону:
decode1 x a = chr (abs x a)
decode2 x = chr (abs x)
Очевидно, decode2
- правильная функция; decode1
даже не проверяет тип. abs
принимает только один аргумент, но decode1
вызывает его с 2! Кроме того, decode1
имеет дополнительный параметр, a
, который нам не нужен.