Пытаясь написать функциональную точку бесплатно, GHCI не одобряет - PullRequest
2 голосов
/ 28 декабря 2011

В качестве упражнения я пытаюсь реализовать интересные части прелюдии вручную.Всякий раз, когда я обнаруживаю возможность освободиться, я использую ее.Однако это привело меня к кирпичной стене в самом неожиданном месте.Используя этот код:

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 кажется уродливым и ненужным, поэтому я пытаюсь вернуть его обратно в стиль без точек.завершается с

 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)

Но этот противный х все еще остается.Как мне это устранить?

1 Ответ

12 голосов
/ 28 декабря 2011

Мы можем переписать ваш код следующим образом:

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
...