Empty Strings with String.all

Hey everyone,

I was working with String.all to determine if my String would have capitals only:
String.all Char.isUpper "ABC" == True

However at some point I had an empty String in this statement.
The result was the same, also True!
String.all Char.isUpper "" == True

  • So I could say: The String "" and "ABC" both equally qualify as String with only capitals in it.
  • Or I could say: The String "" and "abc" both equally qualify as String with only alphabetical characters in it.

That seems a little off to me. Maybe there is a reason behind this ( I didn’t expect that coming…) ?

I also wonder why the documentation does not say anything about this. I took a little time to think about this and a little story came to my mind:

Every evening some people with weird white hats and long hair would stay in front of my rooms door at 6 pm. I heard them talking and so I opened the door. Then I always asked them: ‘Do you all wear white hats ?’. And they replied: ‘Yes, we do’ !

Some weeks later, at some rainy autumn day, it was quiet at 6pm, no talkings. I went to my door, opened it, and to my surprise, nobody was there. I asked ‘Do you all wear white hats ?’ , and they replied: ‘Yes, we do !’.


This behaviour comes from the mathematical definition of “for all” (the universal quantifier).
Similarly, String.any implements the mathematical definition of “there exisits” (the existential quantifier).

The behaviour for the empty string is not obvious, but from a mathematical standpoint is makes a lot of sense. I’ll try to explain:

Mathematically we want to have two properties:

  • “there exists” should only be true if at LEAST one element exists.
  • “there exists an element such that P” should be the same as “not (all elements ensure (not P))”.

Now looking at the empty list we see that

  1. [] |> List.any property should be False.
  2. Therefore, [] |> List.all (not property) should be True

And that’s the reason why you have said behaviour.

Edit: You are right, this should be explained in the documentation. An example is given in List.any and List.all.

I’ve therefore created a new issue over at elm/core.


Maybe the simplicity in the return values is a reason to favor the current implementation?

If you check a string for String.all Char.isUpper and you get False. How could that result change when you append more characters to that string?

If you would use a variant of String.all that returns False for an empty string, String.all Char.isUpper could transition to True by appending more characters to the string.

Maybe a better way to express it: When String.all returns False for a set (of characters), it also returns False for any superset. This constraint makes it simpler.

1 Like

Nice explanation. Related to this is Lisp evaluating (and) to T and (or) to NIL. That led me to read a primer on Logic and it all made sense after that :slight_smile:

One more wiki link that I find useful Vacuous truth.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.