我正在以无指针的方式查看Haskell中的一些函数。在尝试重写一些简单的示例时,我陷入了这个问题
func a b c d = sum $ take 2 $ sort [a, b, c, d]
如何将参数转换成列表形式,这样我就不需要在左边写a b c了?
发布于 2019-02-24 09:15:39
有人在评论中提到了很棒
((((((sum . take 2) .) . sort) .) .) .) . (. ((. ((. return) . (:))) . (.) . (:))) . (.) . (.) . (:)函数。
根据http://pointfree.io的说法
((((sum . take 2 . sort) .) .) .) . (. ((. ((. return) . (:))) . (.) . (:))) . (.) . (.) . (:)也将是正确的。
你不相信我吗?
好的,
让我们beta-reduct第二个选项(它看起来更好)
(((((sum . take 2 . sort) .) .) .) . (. ((. ((. return) . (:))) . (.) . (:))) . (.) . (.) . (:) ) a b c d将其应用于a
((((((sum . take 2 . sort) .) .) .) ((. ((. ((. return) . (:))) . (.) . (:))) ((.) ((.) ((:) a))))) ) b c d增糖运算符:
((((((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来检查我的函数链是否可以用一种更简单的方式表示。他们的关键是找到黄金均值-在某些情况下,这种形式可以帮助,但有时它变成不仅是“无点”,但也是“无点”符号。
发布于 2019-02-26 12:06:44
如果我想用真正的代码编写这个无关点的代码,我只需要考虑列表的结构:
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 == 34under3在(->) a函数器中使用fmap“跳过”3个参数,这样我们就可以将一个单参数函数(sum . take2 . sort)与一个4参数1(list4)函数组合在一起-this使用fmap完全等同于组合(.),只是比内联它更具可读性,因为它在助记方面是“映射到”参数上:
func = ((((sum . take 2 . sort) .) .) .) . list4
where
…list4本身并不真的需要是无指针的,因为没有什么直接的方法可以使它比有指针的版本更易读、更简洁。如果你愿意反向构建list并在之后reverse它,你可以写得更可读性更好一些,但是它仍然有点长并且不是很清楚:
list4 = under3 reverse . fmap (fmap cons . cons) . cons . pure
where cons = flip (:)https://stackoverflow.com/questions/54845781
复制相似问题