Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referential transparency and guard

Tags:

haskell

From Learn You a Haskell for great good! I got:

ghci> [1..50] >>= (\x -> guard ('7' `elem` show x) >> return x)
[7,17,27,37,47]

I changed the example to:

ghci> [1..50] >>= (\x -> if x > 25 then [] else [()] >> return x)
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]

So far so good. But now I want the other 25 numbers:

ghci> [1..50] >>= (\x -> if x > 25 then [()] else [] >> return x)

<interactive>:204:2: error:
    • No instance for (Num ()) arising from the literal ‘1’
    • In the expression: 1
      In the first argument of ‘(>>=)’, namely ‘[1 .. 50]’
      In the expression:
        [1 .. 50] >>= (\ x -> if x > 25 then [()] else [] >> return x)

I can work around it like so:

ghci> [1..50] >>= (\x -> if x < 26 then [] else [()] >> return x)
[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50]

My question is the following: I thought that because of referential transparancy I could replace the guard with an if ... then ... else clause. By proof of the above examples, it seems to work except for the case when "[()]" is first in the clause. Why is this? I try to get a deeper understanding of what is going on here. I am interested in the mechanics of Haskell. This feels inconsistent somehow. I am very interested in your answers.

like image 975
aberends Avatar asked Feb 28 '20 19:02

aberends


People also ask

What is referential transparency example?

Referential transparency means you can take an expression in your program, and replace it with the result of that expression. As an example, if you have the expression 5+4, you can replace that with 9. That's what it means. Now 5+4 is easy because you can do that in your head without running the program.

Why referential transparency is important?

Some functional programming languages enforce referential transparency for all functions. The importance of referential transparency is that it allows the programmer and the compiler to reason about program behavior as a rewrite system.

What is referential transparency in Java?

A function is called referential transparent if it always return the same result value when called with the same argument value. For referential transparency, we need our function to be pure and immutable. Example : The method `String.

Is referential transparency good?

As we all know, it is good practice to avoid functions with side effects. This leaves imperative programmers with pure functions and pure effects. Referential transparency is then a powerful tool for imperative programmers to make their programs easier to reason about, and easier to test.


1 Answers

The reason this fails is because now the compiler reads this as:

(\x -> if x > 25 then [()] else ([] >> return x))

This is important since the else part will return a list of Ints (so [Int]) here, whereas the then part will return a list of a "unit" type () (so [()]) and of course these two do not match. Since an if-then-else should return values of the same type on both the then and the else clause, it thus says that unless () is a Num type (such that it can parse 1 and 50, etc. to that type), we have a problem.

so the >> return x is part of the else … clause. By adding brackets, you can obtain the same result:

(\x -> (if x > 25 then [()] else []) >> return x)

For example:

Prelude> [1..50] >>= (\x -> (if x > 25 then [] else [()]) >> return x)
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]
Prelude> [1..50] >>= (\x -> (if x > 25 then [()] else []) >> return x)
[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50]
like image 76
Willem Van Onsem Avatar answered Sep 28 '22 08:09

Willem Van Onsem