Попытка написать функцию 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 2

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