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
让我们看一个更通用的版本,它使用三个函数 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]
三个月后你想读哪一本?
我正在尝试使用简单的函数链接导出三个参数的函数。
函数的类型应该是
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
让我们看一个更通用的版本,它使用三个函数 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]
三个月后你想读哪一本?