简体   繁体   English

如何修改这个 Haskell function 所以我不必导入 Data.Bool 并且只使用前奏 function?

[英]How do I modify this Haskell function so I don't have to import Data.Bool and only use prelude function?

I want to build function below using only prelude built in function without importing Data.Bool.我想在下面构建 function,只使用 function 中内置的前奏而不导入 Data.Bool。 I want to replace bool function to something else so I don't have to import Data.Bool and function prints same output as below function. I want to replace bool function to something else so I don't have to import Data.Bool and function prints same output as below function. How can I do this so it returns same output?我该怎么做才能返回相同的 output?

increment :: [Bool] -> [Bool]
increment x = case x of
  [] -> [True]
  (y : ys) -> not y : bool id increment y ys

bool from Data.Bool is doing exactly the same thing as a if statement, so it can be a way to implement it: Data.Bool 中的boolif语句的作用完全相同,因此它可以作为一种实现方式:

    bool x y b = if b then y else x

@dfeuer suggested in a comment that you should throw away this code because it's disgusting, and instead try to write it yourself. @dfeuer 在评论中建议您应该丢弃此代码,因为它很恶心,而是尝试自己编写。 This might be distressing to you if you're the one that wrote the code in the first place and can't see why it's disgusting, so allow me to elaborate.如果您是首先编写代码的人并且看不出它为什么令人作呕,那么这可能会让您感到痛苦,所以请允许我详细说明。

In fact, "disgusting" is too strong a word.事实上,“恶心”这个词太强了。 However, the code is unnecessarily complex and difficult to understand.但是,代码过于复杂且难以理解。 A more straightforward implementation does all the processing using pattern matching on the function argument:一个更直接的实现使用 function 参数上的模式匹配来完成所有处理:

increment :: [Bool] -> [Bool]
increment [] = [True]
increment (False : rest) = True  : rest
increment (True  : rest) = False : increment rest

This code is easier to read for most people, because all of the decision logic is at the same "level" and implemented the same way -- by inspecting the three patterns on the left-hand side of the definitions, you can see exactly how the three, mutually exclusive cases are handled at a glance.对于大多数人来说,这段代码更容易阅读,因为所有的决策逻辑都处于相同的“级别”并且以相同的方式实现——通过检查定义左侧的三个模式,您可以确切地看到如何三、互斥案件一目了然。

In contrast, the original code requires the reader to consider the pattern match against an empty versus not empty list, the effect of the "not" computation on the first boolean, the bool call based on that same boolean, and the application of either the function id or the recursive increment on the rest of the boolean list.相反,原始代码要求读者考虑针对空与非空列表的模式匹配、“非”计算对第一个 boolean 的影响、基于相同 boolean 的bool调用以及应用function id或 boolean 列表的 rest 上的递归increment For any given input, you need to consider all four conceptually distinct processing steps to understand what the function is doing, and at the end, you'll probably still be uncertain about which steps were triggered by which aspects of the input.对于任何给定的输入,您需要考虑所有四个概念上不同的处理步骤,以了解 function 正在做什么,最后,您可能仍然不确定哪些步骤是由输入的哪些方面触发的。

Now, ideally, GHC with -O2 would compile both of these version to exactly the same code internally.现在,理想情况下,带有-O2的 GHC 将在内部将这两个版本编译为完全相同的代码。 It almost does.几乎可以。 But, it turns out that due to an apparent optimization bug, the original code ends up being slightly less efficient than this rewritten version because it unnecessarily checks y == True twice.但是,事实证明,由于一个明显的优化错误,原始代码最终的效率略低于这个重写版本,因为它不必要地检查y == True两次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM