How to implement "symmetric non-strict or" in Haskell - haskell

I want to define a function that have the following properties
symmetricLazyOr :: Bool -> Bool -> Bool
symmetricLazyOr True _|_ === True
symmetricLazyOr _|_ True === True
And otherwise it works like the normal or.
Is it even possible in Haskell?
UPDATE
This question is focus on semantic rather than implementation detail. Intuitively, or shall be symmetric, which means or a b === or b a for all given a and b. However, this is not true in Haskell since or _|_ True === _|_ whilst or True _|_ === True.

In other words, you're looking for a function that, given two arguments, attempts to evaluate them both and is true if either argument is true? And in particular, a True result will be returned so long as at least one argument is True and not bottom?
Assuming that's correct, this is possible, but not purely. In order to implement it, you need to race two threads to evaluate each of the branches. The unamb package has some functions for dealing with cases like this (including the parallel-or function por). Another option is lvish, which should also work in this case as I understand it.

Related

Are Haskell guards evaluated sequentially?

What is the order in which Haskell guards are evaluated?
Say that I have a function which returns a Bool:
someFunc :: Bool -> Bool -> Bool
someFunc b1 b2
| b1 == True && b2 == True = True
| b1 == True = False
| b1 == False .....
...
I think it was with Monads and the Do-notation that I read, that actions are sometimes not evaluated sequentially. That is if I have:
do { val1 <- action1
val2 <- action2
action3 }
It might be the case that val2 will be calculated before val1.
Is this the case for guards as well? Can they be evaluated out of order?
If guards were sequential, then if the first statement evaluates to False, and the second evaluates to True, then I can conclude that b2 is False. Does this logic always hold?
Edit: By statements I mean guard 1 to 3
Evaluating the tests within guards can’t have any side-effects — unlike in procedural languages. So the order of evaluating the comparisons or Boolean connectives doesn’t make any difference to the semantics of the program.
Prioritising the branches — that is, each of the lines starting | — is from top to bottom. But really ‘evaluating’ is the wrong concept: it would be OK for the compiler to first evaluate your b1 == False, providing it didn’t take the third branch until it had checked the first two. (GHC doesn’t actually do that; I’m just setting up a straw man.)
Note that in a call to someFunc, the arguments for b1, b2 might be arbitrarily complex expressions. Haskell’s ‘Lazy semantics’ mean that neither of them are evaluated until needed.
Does this logic always hold?
Be careful: if an early guard turns out False, you can’t assume anything about the expressions in it. The compiler might have rearranged them for efficiency, evaluated one out of textual order, then moved on. In your example, if for the first branch it turned out b1 /= True, the compiler might not evaluate b2 at all. So you can’t conclude anything about b2. Indeed b2 might give bottom/infinite calculation, if evaluated.
It’s not just with Monads or Do-notation (which are the same thing) that expressions are not necessarily evaluated in textual order — that’s true across any expressions in any context. (The IO Monad has some dodgy semantics, to make it seem ‘statements’ are executed top-to-bottom.)

In what logical sense is Haskell referentially transparent?

Haskell is sometimes said to "replace equals for equals". The following code shows this isn't true under every interpretation of such a sentence. Wikipedia follows that by saying f(x)=f(x) for every x but that doesn't seem to carry any actual logical content one can test, it would be true by the reflexive law, a tautology.
I think the phrasing needed to make a logical claim like this is more like Leibniz' law (or indistinguishable identicals) where
x=y implies for every f, f(x)=f(y). That claim fails in the illustration below within Haskell. (We override == to make a partition type, but our function definition can freely ignore this and do.)
My question is, can one actually state referential transparency in a way that can be logically tested, and does Haskell actually uphold that logical claim?
module Main (main) where
data Floop = One | Two | Three
instance Eq Floop where
One == One = True
One == Two = False
One == Three = False
Two == One = False
Two == Two = True
Two == Three = True --- 2=3
Three == One = False
Three == Two = True --- 3=2
Three == Three = True
shuffle :: Floop -> Floop
shuffle One = Two
shuffle Two = Two --- fix 2
shuffle Three = One --- move 3
main = print ( (Two == Three) && (shuffle Two /= shuffle Three) )
--- prints "True" proving Haskell violates Leibniz Law
Expanding slightly on what I already said in my comment (thanks #FyodorSolkin for the prod):
You haven't violated referential transparency there, you've just made a pathological Eq instance.
While, as you've observed, the language doesn't forbid you from doing this, nor does it forbid one from making unlawful Functor or Monad instances. (Because it would be totally unfeasible to try to check these laws in practice.) But just because something doesn't cause a compiler error doesn't necessarily mean it's the right thing to do.
So the problem with your example is that while, semantically, (==) in Haskell indeed means "equal", it's just a function, in fact a method of a typeclass - which you can therefore implement however you want. Nothing stops me from defining, for example:
instance (Eq) (a -> b) where
_ == _ = True
and suddenly all functions will be considered "equal" under this definition. Clearly referential transparency will be violated if we consider this to be a true definition of equality. My point is that it's not. In fact it's quite obvious what "equality" means for any type which isn't either a function or otherwise depends on or "contains" function types. (It's actually obvious what equality of functions should mean too, it's just impossible for there to be a general algorithm to determine if two arbitrary functions are equal.)
[EDIT: I just remembered it also doesn't make much sense to talk about equality of IO actions. There might be some other abstract types like that where there's no clear definition of what equality would mean.]
To stray into abstract mathematics for a minute: your Eq instance certainly defines an equivalence relation, which is considered to be a sort of "generalised equality" - and indeed is equality if you use the relation to make equivalence classes. But then it's nonsense to try to apply a function to such a domain/type which differs on different elements of the same equivalence class. Such a thing - as in your example - actually fundamentally fails to be a well-defined mathematical function, because you're defining it on the individual elements in a way which fails to respect the equivalence relation.
f(x)=f(x) for every x
is by no means a tautology. In many popular languages, this property does not hold. Consider Java, for instance:
import java.util.*;
public class Transparency {
static int f(List<Object> xs) {
xs.add(xs.size());
return xs.size();
}
public static void main(String[] args) {
List<Object> x = new ArrayList<>();
System.out.println("Is java referentially transparent? " + (f(x) == f(x)));
}
}
$ javac Transparency.java
$ java Transparency
Is java referentially transparent? false
Here, because f mutates its input x, it would change behavior if we substitute x's definition into f(x) == f(x): f(new ArrayList<>()) == f(new ArrayList<>()) is in fact true, but when using a variable to reduce duplication it evaluates to false. In Haskell, such a substitution is always valid (disregarding cheats like unsafePerformIO).

How to construct an array with multiple possible lengths using immutability and functional programming practices?

We're in the process of converting our imperative brains to a mostly-functional paradigm. This function is giving me trouble. I want to construct an array that EITHER contains two pairs or three pairs, depending on a condition (whether refreshToken is null). How can I do this cleanly using a FP paradigm? Of course with imperative code and mutation, I would just conditionally .push() the extra value onto the end which looks quite clean.
Is this an example of the "local mutation is ok" FP caveat?
(We're using ReadonlyArray in TypeScript to enforce immutability, which makes this somewhat more ugly.)
const itemsToSet = [
[JWT_KEY, jwt],
[JWT_EXPIRES_KEY, tokenExpireDate.toString()],
[REFRESH_TOKEN_KEY, refreshToken /*could be null*/]]
.filter(item => item[1] != null) as ReadonlyArray<ReadonlyArray<string>>;
AsyncStorage.multiSet(itemsToSet.map(roArray => [...roArray]));
What's wrong with itemsToSet as given in the OP? It looks functional to me, but it may be because of my lack of knowledge of TypeScript.
In Haskell, there's no null, but if we use Maybe for the second element, I think that itemsToSet could be translated to this:
itemsToSet :: [(String, String)]
itemsToSet = foldr folder [] values
where
values = [
(jwt_key, jwt),
(jwt_expires_key, tokenExpireDate),
(refresh_token_key, refreshToken)]
folder (key, Just value) acc = (key, value) : acc
folder _ acc = acc
Here, jwt, tokenExpireDate, and refreshToken are all of the type Maybe String.
itemsToSet performs a right fold over values, pattern-matching the Maye String elements against Just and (implicitly) Nothing. If it's a Just value, it cons the (key, value) pair to the accumulator acc. If not, folder just returns acc.
foldr traverses the values list from right to left, building up the accumulator as it visits each element. The initial accumulator value is the empty list [].
You don't need 'local mutation' in functional programming. In general, you can refactor from 'local mutation' to proper functional style by using recursion and introducing an accumulator value.
While foldr is a built-in function, you could implement it yourself using recursion.
In Haskell, I'd just create an array with three elements and, depending on the condition, pass it on either as-is or pass on just a slice of two elements. Thanks to laziness, no computation effort will be spent on the third element unless it's actually needed. In TypeScript, you probably will get the cost of computing the third element even if it's not needed, but perhaps that doesn't matter.
Alternatively, if you don't need the structure to be an actual array (for String elements, performance probably isn't that critical, and the O (n) direct-access cost isn't an issue if the length is limited to three elements), I'd use a singly-linked list instead. Create the list with two elements and, depending on the condition, append the third. This does not require any mutation: the 3-element list simply contains the unchanged 2-element list as a substructure.
Based on the description, I don't think arrays are the best solution simply because you know ahead of time that they contain either 2 values or 3 values depending on some condition. As such, I would model the problem as follows:
type alias Pair = (String, String)
type TokenState
= WithoutRefresh (Pair, Pair)
| WithRefresh (Pair, Pair, Pair)
itemsToTokenState: String -> Date -> Maybe String -> TokenState
itemsToTokenState jwtKey jwtExpiry maybeRefreshToken =
case maybeRefreshToken of
Some refreshToken ->
WithRefresh (("JWT_KEY", jwtKey), ("JWT_EXPIRES_KEY", toString jwtExpiry), ("REFRESH_TOKEN_KEY", refreshToken))
None ->
WithoutRefresh (("JWT_KEY", jwtKey), ("JWT_EXPIRES_KEY", toString jwtExpiry))
This way you are leveraging the type system more effectively, and could be improved on further by doing something more ergonomic than returning tuples.

Erlang: Matching strings in guard statement

Started working with erlang quite recently and ran into the problem above, how do you go about comparing two strings in a guard statement? Tried the string:equal(x,y) method but couldn't get it to work inside a guard.
You could use pattern matching like this:
are_the_same(A, A) ->
true;
are_the_same(_, _) ->
false.
In first clause both arguments are named A which will result in them being pattern matched against each other. Or to be exact first argument will be bind to A variable with use of = operator, and than second argument will be bind to A variable with = operator, but since A is bound already it will be treated as "comparision". You can read more about this in docs.
And of course you could write write first clouse with use of guard like:
are_the_same(A, B) when A =:= B ->
You don't need the function string:equal/2 to compare strings; you can use the operators == or =:=, which are allowed in guard tests. For example:
foo(A, B) when A =:= B ->
equal;
foo(_, _) ->
not_equal.
Though in most cases you'd want to use pattern matching instead, as described in the other answer.
NB: As of Erlang/OTP 20.0, string:equal(A, B) is no longer equivalent to A =:= B. string:equal/2 now operates on grapheme clusters, and there are also string:equal/3 and string:equal/4 that can optionally ignore case when comparing and do Unicode normalisation. So you need to understand what you mean by "equal" before settling on a comparison method.
The functions you can use in guards are limited because of the nature of Erlang's scheduling; specifically, Erlang aims to avoid side-effects in guard statements (e.g., calling to another process) because guards are evaluated by the scheduler and do not count against reductions. This is why string:equal does not work.
That being said, you can use Erlang's pattern matching to match strings. Please bear in mind the use of strings as lists, binaries, or iolists (nested lists/binaries) in Erlang, and make sure you're testing/passing strings of the right type (iolists are particularly hard to pattern match and are usually best handled with the re module, or converting them to binaries via iolist_to_binary).
For example, say we want a function that tests to see if a string begins with "foo":
bar("foo" ++ _Rest) -> true;
bar(<<"foo", Rest/binary>>) -> true;
bar(_Else) -> false.
If you just want to test for a particular string, it's even easier:
bar("foo") -> true;
bar(<<"foo">>) -> true;
bar(_Else) -> false.

What makes a good name for a helper function?

Consider the following problem: given a list of length three of tuples (String,Int), is there a pair of elements having the same "Int" part? (For example, [("bob",5),("gertrude",3),("al",5)] contains such a pair, but [("bob",5),("gertrude",3),("al",1)] does not.)
This is how I would implement such a function:
import Data.List (sortBy)
import Data.Function (on)
hasPair::[(String,Int)]->Bool
hasPair = napkin . sortBy (compare `on` snd)
where napkin [(_, a),(_, b),(_, c)] | a == b = True
| b == c = True
| otherwise = False
I've used pattern matching to bind names to the "Int" part of the tuples, but I want to sort first (in order to group like members), so I've put the pattern-matching function inside a where clause. But this brings me to my question: what's a good strategy for picking names for functions that live inside where clauses? I want to be able to think of such names quickly. For this example, "hasPair" seems like a good choice, but it's already taken! I find that pattern comes up a lot - the natural-seeming name for a helper function is already taken by the outer function that calls it. So I have, at times, called such helper functions things like "op", "foo", and even "helper" - here I have chosen "napkin" to emphasize its use-it-once, throw-it-away nature.
So, dear Stackoverflow readers, what would you have called "napkin"? And more importantly, how do you approach this issue in general?
General rules for locally-scoped variable naming.
f , k, g, h for super simple local, semi-anonymous things
go for (tail) recursive helpers (precedent)
n , m, i, j for length and size and other numeric values
v for results of map lookups and other dictionary types
s and t for strings.
a:as and x:xs and y:ys for lists.
(a,b,c,_) for tuple fields.
These generally only apply for arguments to HOFs. For your case, I'd go with something like k or eq3.
Use apostrophes sparingly, for derived values.
I tend to call boolean valued functions p for predicate. pred, unfortunately, is already taken.
In cases like this, where the inner function is basically the same as the outer function, but with different preconditions (requiring that the list is sorted), I sometimes use the same name with a prime, e.g. hasPairs'.
However, in this case, I would rather try to break down the problem into parts that are useful by themselves at the top level. That usually also makes naming them easier.
hasPair :: [(String, Int)] -> Bool
hasPair = hasDuplicate . map snd
hasDuplicate :: Ord a => [a] -> Bool
hasDuplicate = not . isStrictlySorted . sort
isStrictlySorted :: Ord a => [a] -> Bool
isStrictlySorted xs = and $ zipWith (<) xs (tail xs)
My strategy follows Don's suggestions fairly closely:
If there is an obvious name for it, use that.
Use go if it is the "worker" or otherwise very similar in purpose to the original function.
Follow personal conventions based on context, e.g. step and start for args to a fold.
If all else fails, just go with a generic name, like f
There are two techniques that I personally avoid. One is using the apostrophe version of the original function, e.g. hasPair' in the where clause of hasPair. It's too easy to accidentally write one when you meant the other; I prefer to use go in such cases. But this isn't a huge deal as long as the functions have different types. The other is using names that might connote something, but not anything that has to do with what the function actually does. napkin would fall into this category. When you revisit this code, this naming choice will probably baffle you, as you will have forgotten the original reason that you named it napkin. (Because napkins have 4 corners? Because they are easily folded? Because they clean up messes? They're found at restaurants?) Other offenders are things like bob and myCoolFunc.
If you have given a function a name that is more descriptive than go or h, then you should be able to look at either the context in which it is used, or the body of the function, and in both situations get a pretty good idea of why that name was chosen. This is where my point #3 comes in: personal conventions. Much of Don's advice applies. If you are using Haskell in a collaborative situation, then coordinate with your team and decide on certain conventions for common situations.

Resources