Попытка написать функциональную точку бесплатно, 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 все еще остается. Как мне это устранить?


person TheIronKnuckle    schedule 28.12.2011    source источник
comment
ThelronKnuckle: Если вы еще этого не сделали, поищите в SO вопросы о разнице между ($) и (.) — я думаю, вы найдете эти вопросы/ответы полезными.   -  person Thomas M. DuBuisson    schedule 28.12.2011


Ответы (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
person hammar    schedule 28.12.2011
comment
Бессовестная затычка, я залил составной пакет на хакер, чтобы обеспечить удобство функций для болванщика и друзей. - person Dan Burton; 28.12.2011
comment
Сиськастый оператор XD должен будет использовать это как преимущество при сутенерстве haskell моим товарищам. - person TheIronKnuckle; 03.02.2012
comment
Часто ли используется оператор boob в реальном коде? Какой самый чистый способ справиться с такой ситуацией? Не лучше ли просто оставить его с баллами (mynotelem x = not . elem x или mynotelem x y = not $ elem x y)? - person Brandon Pickering; 03.01.2013