pointfree 添加到 haskell 中的列表

pointfree add to list in 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]

?

稍微尝试一下,也许它会给你一些想法...

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

让我们看一个更通用的版本,它使用三个函数 fgh:

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

我们现在要做的就是插入fgh的定义:

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

我没有检查是否有更短的版本,但由于这与 pointfree.io 的结果相同,它应该或多或少是最优的。

也就是说,如果你比较

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

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

三个月后你想读哪一本?