Adr*_*May 2 haskell lazy-evaluation
这段代码:
import Data.Foldable
import Debug.Trace
factors :: [Bool]
factors = [True, True, False, True, True, True, True, True]
andy :: Bool -> Bool -> Bool
andy False _ = False
andy True False = False
andy True True = True
tandy :: Bool -> Bool -> Bool
tandy a b = let c = a `andy` b in trace (show a ++ " & " ++ show b ++ " = " ++ show c) c
wonder :: Bool
wonder = foldl tandy True factors
Run Code Online (Sandbox Code Playgroud)
当我评估时这样说wonder:
True & True = True
True & True = True
True & False = False
False & True = False
False & True = False
False & True = False
False & True = False
False & True = False
Run Code Online (Sandbox Code Playgroud)
但我希望它早点停止。我已经尝试过用一切可以想象到的东西来代替foldl和 来&&代替andy,但似乎从未得到提示。
在我看来,该行andy False _ = False不会邀请编译器评估第二个参数。我没有强迫任何严格的要求。这是怎么回事?甚至 C 也可以做得更好。
tandy尽管andy不是,但这两个参数都是严格的。这是因为追踪。您要求它在调用中显示两个输入trace,因此它必须评估两个参数。
考虑“tandy2”:
tandy2 :: Bool -> Bool -> Bool
tandy2 False _ = trace ("False & anything = False") False
tandy2 True b = trace ("True & " ++ show b ++ " = False") b
Run Code Online (Sandbox Code Playgroud)
它不会在跟踪中盲目地评估两个参数,而是小心地仅评估否则会评估的相同参数。这使得它实际上反映了与之前相同的严格属性andy。
尝试使用tandy2with foldr,您会发现它一旦遇到 就停止计算False。
$ ghci
GHCi, version 9.2.1: https://www.haskell.org/ghc/ :? for help
ghci> import Debug.Trace
ghci> let tandy2 False _ = trace ("False & anything = False") False ; tandy2 True b = trace ("True & " ++ show b ++ " = False") b
ghci> foldr tandy2 True []
True
ghci> foldr tandy2 True [True]
True & True = False
True
ghci> foldr tandy2 True [True, False]
False & anything = False
True & False = False
False
ghci> foldr tandy2 True [True, False, True]
False & anything = False
True & False = False
False
Run Code Online (Sandbox Code Playgroud)
就这样吧。False它永远不会多次评估分支。