У вас это почти правильно. Я считаю, что самый простой способ начать изучение композиции функций с .
- это сначала использовать $
.
Итак, у вас есть список
twoFilters xs = xs
Вы хотите отфильтровать по greaterThanOne
twoFilters xs = filter greaterThanOne $ xs
Вы также хотите отфильтровать по lessThanTen
twoFilters xs = filter lessThanTen $ filter greaterThanOne $ xs
Теперь двигайтесь слева направо, заменяя все $
с .
, за исключением последнего $
twoFilters xs = filter lessThanTen . filter greaterThanOne $ xs
Теперь вы можете использовать скобки вместо $
:
twoFilters xs = (filter lessThanTen . filter greaterThanOne) xs
Или просто определите функцию pointfree:
twoFilters = filter lessThanTen . filter greaterThanOne
Я считаю, что версия в скобках - самая важная. Это показывает, что вы объединяете две частично примененные функции filter lessThanTen
и filter greaterThanOne
в одну функцию мегафильтрации, с помощью .
и , а затем вы применяете список к ней. Вам необходимо заключить их в скобки, потому что .
связывается менее плотно, чем приложение-функция, через пробел (пробел можно считать версией $
с высокой степенью надежности). Помните, что когда вы используете .
, вы объединяете две функции в одну мега-функцию.
Уместно проверить подпись типа .
(.) :: (b -> c) -> (a -> b) -> a -> c
Функции, которые вы передаете, должны «выровняться» с очень специфическими сигнатурами типов (они должны быть совместимы для слияния). Но, честно говоря, ключ учится распознавать, когда приложение функции (с пробелом) связывается более тесно, чем вы предполагаете, и путает сигнатуры типов функций, которые вы пытаетесь составить. Во всяком случае, так было для меня.