问题
A friend of us is teaching to us the basics of functional programming in Haskell, and he started to write the rarest thing I ever saw:
He started with something not so amazing, but pretty cool:
(x,y) = (10,20)
(z:zs) = 0 : [1..]
and shows in the prelude:
prelude> x
10
prelude> z
0
prelude> takeN 3 zs
[1,2,3]
so far, so good... I didn't know you could bind the values like that
(x,y) = (10,20)
(z:zs) = 0 : [1..]
True = False -- HERE
What!? Everyone in the class thought, ok, something will go wrong, but not even the code compiled, then it runs:
prelude> x
10
prelude> 4
4
prelude> True
True
(I read the question What does `let 5 = 10` do? Is it not an assignment operation? and I'm not using any let here, in my example I write the code in a file and the execute it, so my question is not answered yet, none of that answers are useful for me.)
回答1:
Both where and let introduce defining equations using lazy patterns.
In any module, all the top-level definitions are under a where.
module Main where
-- ^^^^^
x, y :: Int
(x, y) = undefined
main :: IO ()
main = putStrLn "hello!"
The above program will print "hello", as intended. The pattern matching against (x, y) would diverge if it were strict, but since it is lazy it does not -- the undefined expression never gets evaluated.
Definitions typed in GHCi are also under an implicit let.
After knowing this, the issue mentioned in the question is exactly the one in the let 5 = 10 question.
回答2:
In Haskell a let “binding” is doing pattern matching. There are precisely two types of pattern-matching-binding in Haskell: You can either write P = x where P is a pattern or you may write v1 p1 p2 ... pn = x where each pi is a pattern. This defines (part of) a function v1. What is a pattern?
A pattern is either a variable v which causes v to be bound to whatever is being matched when the match is successful. Or a pattern may be a constant like 7 where when the matching is done it succeeds only if the thing being matched is equal to the constant. Or a pattern may be a variant of a data type: If Foo is a variant (constructor) for the type Bar taking n parameters then Foo p1 p2 ... pn, where the pi are patterns, is a pattern which looks at an object of type Bar and successfully matches if it is of the Foo variant and each of the pi successfully match.
Because Haskell is lazy, the only way to force the pattern matching to happen is to use a variable which was bound by pattern matching. So one may force the binding of x in let (x,5)=(6,6) by using x and this cause a matching failure. If a variant has no parameters there is no way for the matching to be forced so there is no way for the match to fail. Thus let True = False would fail if you ever got the match to happen but because there is no way to get the match to happen, there is no error. Note that you are not rebinding True but using it as a pattern with no arguments.
来源:https://stackoverflow.com/questions/48010100/is-true-false-understanding-binding-and-pattern-matching