Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand Data.Text all function

Tags:

haskell

I was playing around with the Data.Text all function, doing some trivial examples and combining them when I found that the evaluation of this trivial piece of code in GHCI is evaluating to True, the question is why?

import qualified Data.Text  as T
T.all C.isSymbol (T.filter C.isNumber (T.pack "asad"))
GHCI => True

I am baffled because the evaluation of:

(T.filter C.isNumber (T.pack "asad"))
GHCI => ""

Is this a bug? or is by design?

like image 678
Cloxure Avatar asked Oct 30 '25 14:10

Cloxure


1 Answers

From high school math, you may remember learning about sums and products like the ones drawn on this page and that one. You might recall learning that when a sum doesn't have any terms, we say it's 0, and when a product doesn't have any terms, we say it's 1. But did you ever learn why we pick those definitions?

In Haskell, we can see that the base library reflects those facts in its definitions of sum and product:

> sum []
0
> product []
1

One reason these choices are nice is the following property: if we have a sum with a bunch of terms, we can split up the terms arbitrarily into two groups, sum them separately, and add the results together. Using a Haskell-inspired syntax, we might express a similar property like this:

forall xs ys, sum xs + sum ys = sum (xs ++ ys)

One interesting thing about this property is that it forces our hand in how we define the sum of an empty list -- it has to be 0!

sum [] + sum ys = sum ([] ++ ys) = sum ys

Now just subtract sum ys from both sides. A similar property for products,

forall xs ys, product xs * product ys = product (xs ++ ys)

forces us to choose 1:

product [] * product ys = product ([] ++ ys) = product ys

Is there a similar property for all? Yes! If all the elements of one list satisfy a predicate, and all the elements of another list satisfy that same predicate, then when you concatenate those lists, all the elements still satisfy that predicate.

forall p xs ys, all p xs && all p ys = all p (xs ++ ys)

By similar reasoning to that done above, we can get a pretty good idea for what all should do on empty lists:

forall p ys, all p [] && all p ys = all p ([] ++ ys) = all p ys

The simplest way to validate the equation all p [] && X = X is to choose all p [] = True -- and this is exactly what's been done.

If you'd like to practice this kind thinking, can you think of a property like this for any? What should any p [] do to validate that property? Suppose I define:

lcms :: Integral a => [a] -> a
lcms (x:xs) = lcm x (lcms xs)

where

-- lcm x y is the smallest positive integer that both x and y divide.
lcm :: Integral a => a -> a -> a 

What should I pick to be the answer for lcms []?

like image 134
Daniel Wagner Avatar answered Nov 01 '25 13:11

Daniel Wagner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!