Haskell中的Pointfree函数-将参数转换为列表

时间:2019-02-23 20:15:17

标签: haskell

我正在以无点样式查看Haskell中的某些功能。在尝试重写一些简单的示例时,我陷入了困境

func a b c d = sum $ take 2 $ sort [a, b, c, d]

如何将参数转换为列表形式,这样我就不需要在左侧写上a b c

2 个答案:

答案 0 :(得分:2)

评论中有人提到很棒

((((((sum . take 2) .) . sort) .) .) .) . (. ((. ((. return) . (:))) . (.) . (:))) . (.) . (.) . (:)

功能。

根据http://pointfree.io

((((sum . take 2 . sort) .) .) .) . (. ((. ((. return) . (:))) . (.) . (:))) . (.) . (.) . (:)

也是正确的。

你不相信我吗?

确定

让我们降低beta的第二个选择(imo看起来更好)

(((((sum . take 2 . sort) .) .) .) . (. ((. ((. return) . (:))) . (.) . (:))) . (.) . (.) . (:) ) a b c d

将其应用于a

((((((sum . take 2 . sort) .) .) .) ((. ((. ((. return) . (:))) . (.) . (:))) ((.) ((.) ((:) a))))) ) b c d

Ensugar运算符:

((((((sum . take 2 . sort) .) .) .) ((. ((. ((. return) . (:))) . (.) . (:))) (((a:).).))) ) b c d

应用部分应用的合成:

((((sum . take 2 . sort) .) .) . ((. ((. ((. return) . (:))) . (.) . (:))) (((a:).).))) b c d

将其应用于b

((((sum . take 2 . sort) .) .) (((. ((. ((. return) . (:))) . (.) . (:))) (((a:).).)) b)) c d

通过应用部分应用的b将应用于.的计算函数:

((((sum . take 2 . sort) .) .) ( (((a:).).) . ((. ((. return) . (:))) . (.) . (:)) $ b)) c d)

解决构图:

((((sum . take 2 . sort) .) .) ( (((a:).).) (((. ((. return) . (:))) . (.) . (:)) b))) c d

应用于b

((((sum . take 2 . sort) .) .) ( (((a:).).) ((. ((. return) . (:))) ((b:) .)))) c d

应用合成(2x):

(((sum . take 2 . sort) .) . ((((a:).).) (( ((b:) .) . ((. return) . (:)))))) c d

应用于c并解决组成问题:

((sum . take 2 . sort) .) (((((a:).).) (( ((b:) .) . ((. return) . (:))))) c) d

应用部分应用的合成:

((sum . take 2 . sort) .) (((((a:).) . (( ((b:) .) . ((. return) . (:)))))) c) d

应用于c并解决组成问题:

((sum . take 2 . sort) .) (((a:).) ((( ((b:) .) . ((. return) . (:)))) c)) d

应用于c并解决组成问题:

((sum . take 2 . sort) .) (((a:).) (((b:) .) (((. return) . (:)) c))) d

解决构图:

((sum . take 2 . sort) .) ((a:) . (((b:) .) (((. return) . (:)) c))) d

应用部分应用的合成:

((sum . take 2 . sort) . ((a:) . (((b:) .) (((. return) . (:)) c)))) d

解决构图:

(sum . take 2 . sort) (((a:) . (((b:) .) (((. return) . (:)) c))) d)

应用于d并解决组成问题:

(sum . take 2 . sort) ((a:) ((((b:) .) (((. return) . (:)) c)) d))

应用部分应用的合成:

(sum . take 2 . sort) ((a:) (((b:) . (((. return) . (:)) c)) d))

应用于d并解决组成问题:

(sum . take 2 . sort) ((a:) (((b:) ((((. return) . (:)) c) d))))

应用于c并解决组成问题:

(sum . take 2 . sort) ((a:) (((b:) (((((c:). return))) d))))

应用于d并解决组成问题:

(sum . take 2 . sort) ((a:) ((b:) ((c:) (return d))))

转换为中缀运算符并解析return

(sum . take 2 . sort) (a : (b : (c : (d : []))))

(sum . take 2 . sort) [a, b, c, d]

解析合成并使用$运算符

sum $ take 2 $ sort $ [a, b, c, d]

我们该死! 如果将其粘贴到带有彩虹括号的编辑器中,将更易于阅读。


如您所见,并非所有内容都以无点形式显得更加优雅。有时,这很简单,不仅要理解该功能为什么起作用,而且什至可以做什么,也可能使人困惑。请注意,此函数是特定于长度的-如果您尝试以这种方式创建更大的列表,它将变得更大。

另一方面,我经常使用http://pointfree.io来检查我的函数链是否可以用更简单的方式表示。他们的关键是找到中庸之道–在某些情况下,这种形式可以提供帮助,但有时不仅变成“无点”符号,而且还变成“无点”符号。

答案 1 :(得分:2)

如果我想用真实的代码编写这个免费的东西,我只是考虑一下列表的构造:

list4 a b c d = [a, b, c, d]
under3 = fmap . fmap . fmap
func = under3 (sum . take 2 . sort) . list4

func 30 4 1000 200 == 34

under3fmap函子中使用(->) a“跳过” 3个参数,因此我们可以将1参数函数(sum . take2 . sort)与4参数( list4)— fmap的这种用法完全等同于组合(.),比内联它更具可读性,因为助记符是“映射”参数:

func = ((((sum . take 2 . sort) .) .) .) . list4
  where
    …

list4本身并不需要完全没有意义,因为没有一种直接的方法可以使它比有意义的版本更具可读性和简洁性。如果您愿意反向构建列表,然后在以后reverse进行构建,则可以更轻松一点地编写它,但是它仍然有点长而且不太清楚:

list4 = under3 reverse . fmap (fmap cons . cons) . cons . pure
  where cons = flip (:)