2016-03-08 3 views
0

Я пытаюсь получить функцию трех аргументов, используя простую цепочку функций.
Функция должна быть типаpointfree добавить в список в haskell

addToList :: a -> a -> a -> [a] 

и быть pointfree аналог

addToList :: a b c = (a : (b : (c : []))) 

До сих пор я понял,

addToList = ((.)((.) (flip (:)) . (flip (:))) . (flip (:))) [] 

Но он работает в обратном направлении:

Prelude> addToList 4 5 6 
[6,5,4] 

и выглядит громоздким.

Как можно получить что-то хорошее, как

(.) (.) (.) (:) (:) (: []) 

, который работает следующим образом:

Prelude> addToList 4 5 6 
[4,5,6] 

?

+1

Вы можете просто использовать [pointfree.io] (http://pointfree.io/), который дает: 'addToList = (. ((. Return). (:))). (.). (:) ' – Bakuriu

+6

И это намного яснее, чем' addToList a b c = [a, b, c] '. \*вздох\* – Zeta

ответ

3

Давайте посмотрим на более общую версию, которая использует три функции f, g и h:

func a b c = f a (g b (h c)) 

В нашем случае, f = (:), g = (:) и h = return, но мы можем использовать это для любой тройки функций, которые следуют по той же схеме:

func a b c = (f a . g b . h) c 

Для следующего шага, написать первое приложение (.) в виде префикса, так что легче сочетать (.) (f a), а остальные позже:

func a b = (.) (f a) (g b . h) 
     = (.) (f a) (g b . h) 
     = (.) (f a) ((.) (g b) h) 
     = (.) (f a) (flip (.) h (g b)) 
     = (.) (f a) ((flip (.) h . g) b) 
     = (.) (f a) . (flip (.) h . g) b 

Теперь мы можем сделать то же самое для a:

func a = (.) (f a) . (flip (.) h . g) 
     = (.) ((.) (f a)) (flip (.) h . g) 
     = flip (.) (flip (.) h . g) ((.) (f a)) 
     = flip (.) (flip (.) h . g) . (.) (f a) 
     = flip (.) (flip (.) h . g) . (.) . f a 

flip (.) x Поскольку это (.x) мы можем избавиться от flip:

func = flip (.) (flip (.) h . g) . (.) . f 
    = flip (.) ((.h) . g) . (.) . f 
    = (.((.h) . g)) . (.) . f 

Все, что нужно сделать сейчас, чтобы вставить определения f, g и h:

func = (.((.return) . (:))) . (.) . (:) 

Я не проверял, есть ли более короткий вариант, но так как это тот же самый результат поскольку pointfree.io дает, он должен быть более или менее оптимальным.

Это, как говорится, если вы сравните

addToList = (.((.return) . (:))) . (.) . (:) 

с

addToList a b c = [a, b, c] 

, который бы вы хотели прочитать в три месяца?

0

Просто играть с этим немного, может быть, это даст вам некоторые идеи ...

-- | >>> append [4,5] 6 
-- [4,5,6] 
append :: [a] -> a -> [a] 
append = flip (flip (++) . (: [])) 

-- | >>> f1 4 
-- [4] 
f1 :: a -> [a] 
f1 = (:[]) 

-- | >>> f2 4 5 
-- [4,5] 
f2 :: a -> a -> [a] 
f2 = append . f1 

-- | >>> f3 4 5 6 
-- [4,5,6] 
f3 :: a -> a -> a -> [a] 
f3 = (append .) . f2 

-- | >>> f4 4 5 6 7 
-- [4,5,6,7] 
f4 :: a -> a -> a -> a -> [a] 
f4 = ((append .) .) . f3