Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is operator && strict in Haskell?

For example, I have an operation fnB :: a -> Bool that makes no sense until fnA :: Bool returns False. In C I may compose these two operations in one if block:

if( fnA && fnB(a) ){ doSomething; }

and C will guarantee that fnB will not execute until fnA returns false.

But Haskell is lazy, and, generally, there is no guarantee what operation will execute first, until we don't use seq, $!, or something else to make our code strict. Generally, this is what we need to be happy. But using && operator, I would expect that fnB will not be evaluated until fnA returns its result. Does Haskell provide such a guarantee with &&? And will Haskell evaluate fnB even when fnA returns False?

like image 333
Dmitry Bespalov Avatar asked Sep 30 '11 15:09

Dmitry Bespalov


People also ask

What is the purpose of the IS operator?

The is operator is used to check if the run-time type of an object is compatible with the given type or not. It returns true if the given object is of the same type otherwise, return false. It also returns false for null objects.

What is the is operator in Python?

Python is operator compares two variables and returns True if they reference the same object. If the two variables reference different objects, the is operator returns False . In other words, the is operator compares the identity of two variables and returns True if they reference the same object.

What is the difference between == and is?

== is for value equality. It's used to know if two objects have the same value. is is for reference equality. It's used to know if two references refer (or point) to the same object, i.e if they're identical.

Is operator example in C#?

static bool IsFirstFridayOfOctober(DateTime date) => date is { Month: 10, Day: <=7, DayOfWeek: DayOfWeek.Friday }; In the preceding example, the is operator matches an expression against a property pattern (available in C# 8.0 and later) with nested constant and relational (available in C# 9.0 and later) patterns.


1 Answers

The function (&&) is strict in its second argument only if its first argument is True. It is always strict in its first argument. This strictness / laziness is what guarantees the order of evaluation.

So it behaves exactly like C. The difference is that in Haskell, (&&) is an ordinary function. In C, this would be impossible.

But Haskell is lazy, and, generally, there are no guarantee what operation will execute first, until we don't use seq, $!, or something else to make our code strict.

This is not correct. The truth is deeper.

Crash course in strictness:

We know (&&) is strict in its first parameter because:

⊥ && x = ⊥

Here, ⊥ is something like undefined or an infinite loop (⊥ is pronounced "bottom"). We also know that (False &&) is non-strict in its second argument:

False && ⊥ = False

It can't possibly evaluate its second argument, because its second argument is ⊥ which can't be evaluated. However, the function (True &&) is strict in its second argument, because:

True && ⊥ = ⊥

So, we say that (&&) is always strict in its first argument, and strict in its second argument only when the first argument is True.

Order of evaluation:

For (&&), its strictness properties are enough to guarantee order of execution. That is not always the case. For example, (+) :: Int -> Int -> Int is always strict in both arguments, so either argument can be evaluated first. However, you can only tell the difference by catching exceptions in the IO monad, or if you use an unsafe function.

like image 152
Dietrich Epp Avatar answered Sep 20 '22 09:09

Dietrich Epp