Попытка написать функцию point free, GHCI не одобряет
В качестве упражнения я пытаюсь реализовать интересные части прелюдии вручную. Всякий раз, когда я замечаю возможность пойти в точку бесплатно, я использую ее. Однако это привело меня к кирпичной стене в самом неожиданном месте. Используя этот код:
myelem _ [] = False
myelem x y = if x == head y then True else myelem x (tail y)
Я пытаюсь реализовать notElem
. Вот мои попытки:
-- First
mynotelem = not myelem
По понятным причинам взрывается из-за несоответствия типов. Это легко исправить:
-- Second
mynotelem x y = not (myelem x y)
Однако явное объявление аргументов x и y кажется уродливым и излишне, поэтому я пытаюсь вернуть его в свободный стиль.
-- Third
mynotelem = not $ myelem
Который терпит неудачу с
Couldn't match expected type `Bool'
with actual type `a0 -> [a0] -> Bool'
In the second argument of `($)', namely `myelem'
In the expression: not $ myelem
In an equation for `mynotelem': mynotelem = not $ myelem
Честно говоря, типы все еще не совпадают. Но как это исправить? И снова вы можете перейти прямо к
-- Fourth
mynotelem x y = not $ myelem x y
Это работает, но кажется опасно близким к тому, чтобы просто ходить по кругу. Я обнаружил, что можно исключить один из аргументов:
-- Fifth
mynotelem x = not . (myelem x)
Но этот надоедливый x все еще остается. Как мне его устранить?1 ответ:
Мы можем переписать ваш код следующим образом:
mynotelem x = not . (myelem x) = (not .) (myelem x)
Теперь признаем, что это просто
h x = f (g x)
сf = (not .)
иg = myelem
, поэтому мы можем записать его без точки с другим использованием оператора(.)
какh = f . g
:mynotelem = (not .) . myelem
Обратите внимание, как шаблон продолжается при составлении с функциями с большим количеством аргументов:
> let f x y z = x+y+z > (((sqrt .) .) . f) 1 2 3 2.449489742783178
В качестве альтернативы, вы также можете написать его с помощью этой забавной композиции операторов композиции:
mynotelem = ((.).(.)) not myelem
Для большего количества аргументов шаблон продолжается следующим образом: это:
> ((.).(.).(.)) sqrt f 1 2 3 2.449489742783178