cit. & loll – 82

Il Web è grande; io ci ho trovato questo 😋


Dadgad – Pensieri
social-cosi
::: Beppe Beppetti

Any software criticism that does not take tradeoffs into account is useless
::: rkoutnik

Io credo a quello che vedo
OT? parliamone…
::: altrodame

How the rest of the world imagines programming
::: MIT_CSAIL

Some data for machine learning algorithms right here…
::: geospacedman

If you can cope with JavaScript or with many of the other systems that are out there
::: freizl

This software system uses the ‘Onion’ pattern
::: RichRogersIoT

Never give up. Today is hard, tomorrow will be worse
::: RichRogersIoT

Fall in love with some activity, and do it!
::: ProfFeynman

A good software framework or tool is like a convex object
::: mariofusco

Maintaining an open-source project
::: kelseyhightower

If you have error reporting and your entire team ignores it
::: greydnls

How do I increase the frequency…
vale anche per me; e sarei interessato alla soluzione
::: lizardbill

Complexity in software design can be managed precisely through hierarchical composability, or stochastically through democratic collaboration
::: jdegoes

Bitcoin is like the transcompiler
::: YanJeanLee

How Bob started the robocalypse
::: GoComics

The noteworthy thing about this plan
::: wallingf

The key to efficient development
::: CodeWisdom

Words of wisdom
::: FailsWork

Di sicuro esiste una #parolatedesca
::: g3p5

The influx of capital will support & train many software engineers and will help usher in a golden era of functional programming
::: jdegoes

In futuro auto volanti solcheranno i nostri cieli
::: parcesepulto

No, tranquilli, è normale che il kernel vada in crash
::: fulcorno

Organization is what you do before you do it
::: JohnDCook

me trying to convince my friends to learn haskell
::: cpp99x

Mamma quanto odio la funzione
::: medeoTL

Who says we never get a fairy tale ending?
::: jdegoes

Don’t patch bugs out
::: CodeWisdom

Very cool robot that can ride a bicycle
::: uxlinks

Sometimes the problem is
::: CodeWisdom

Developers love to rewrite from scratch
::: wallingf

You can never use the same
::: jonathanccast

The word ‘crypto’ has inevitably become a synonym for cryptocurrencies
::: manisha72617183

Please before submitting your paper, consider that another human will dedicate some of his short life-time to read it and try to evaluate it
::: LegalizeBrain

Current status
::: RichRogersIoT

Pen & paper is still the most underrated tool
::: RichRogersIoT

Good elementary school advice for using @twitter
::: ValaAfshar

Roses are red
::: loislnessie

Comparison between 5,000 and 50,000 prime numbers plotted in polar coordinates
::: fermatslibrary

Enthusiastic open supporter
::: unix_byte

Programming languages may be different but they all sought out to solve a problem
::: CodeWisdom

How do YOU combine IO actions?
::: chris__martin

Learning to program is personal
::: karen_brennan

Note to future self: never underestimate the importance of liking the project
::: volothamp

That’s wonderful. We will soon have bots that write verbose and probably unnecessary documents (since we don’t have the time for that) and bots that summarize them for us (since we don’t have the time for that)
::: MarcoCantamessa

Ben fatto è meglio
::: MomentiZen

Annunci

Haskell – 116 – un po’ di monadi – 4

Continuo da qui, copio qui.

La do notation
Monads in Haskell are so useful that they got their own special syntax called do notation. We’ve already encountered do notation when we were doing I/O and there we said that it was for gluing together several I/O actions into one. Well, as it turns out, do notation isn’t just for IO, but can be used for any monad. Its principle is still the same: gluing together monadic values in sequence. We’re going to take a look at how do notation works and why it’s useful.

Consider this familiar example of monadic application:

Prelude> Just 3 >>= (\x -> Just (show x ++ "!"))
Just "3!"

Been there, done that. Feeding a monadic value to a function that returns one, no big deal. Notice how when we do this, x becomes 3 inside the lambda. Once we’re inside that lambda, it’s just a normal value rather than a monadic value. Now, what if we had another >>= inside that function? Check this out:

Prelude> Just 3 >>= (\x -> Just "!" >>= (\y -> Just (show x ++ y)))
Just "3!"

Ah, a nested use of >>=! In the outermost lambda, we feed Just "!" to the lambda \y -> Just (show x ++ y). Inside this lambda, the y becomes "!". x is still 3 because we got it from the outer lambda. All this sort of reminds me of the following expression:

Prelude> let x = 3; y = "!" in show x ++ y
"3!"

The main difference between these two is that the values in the former example are monadic. They’re values with a failure context. We can replace any of them with a failure:

Prelude> Nothing >>= (\x -> Just "!" >>= (\y -> Just (show x ++ y)))
Nothing
Prelude> Just 3 >>= (\x -> Nothing >>= (\y -> Just (show x ++ y)))
Nothing
Prelude> Just 3 >>= (\x -> Just "!" >>= (\y -> Nothing))
Nothing

In the first line, feeding a Nothing to a function naturally results in a Nothing. In the second line, we feed Just 3 to a function and the x becomes 3, but then we feed a Nothing to the inner lambda and the result of that is Nothing, which causes the outer lambda to produce Nothing as well. So this is sort of like assigning values to variables in let expressions, only that the values in question are monadic values.

To further illustrate this point, let’s write this in a script and have each Maybe value take up its own line:

foo.hs

foo :: Maybe String
foo = Just 3   >>= (\x ->
      Just "!" >>= (\y ->
      Just (show x ++ y)))
Prelude> :l foo
[1 of 1] Compiling Main             ( foo.hs, interpreted )
Ok, modules loaded: Main.
*Main> foo
Just "3!"

To save us from writing all these annoying lambdas, Haskell gives us do notation. It allows us to write the previous piece of code like this:

foo-do.hs

foo :: Maybe String
foo = do
    x <- Just 3
    y <- Just "!"
    Just (show x ++ y)
Prelude> :l foo-do
[1 of 1] Compiling Main             ( foo-do.hs, interpreted )
Ok, modules loaded: Main.
*Main> foo
Just "3!"

It would seem as though we’ve gained the ability to temporarily extract things from Maybe values without having to check if the Maybe values are Just values or Nothing values at every step. How cool! If any of the values that we try to extract from are Nothing, the whole do expression will result in a Nothing. We’re yanking out their (possibly existing) values and letting >>= worry about the context that comes with those values. It’s important to remember that do expressions are just different syntax for chaining monadic values.

In a do expression, every line is a monadic value. To inspect its result, we use <-. If we have a Maybe String and we bind it with <- to a variable, that variable will be a String, just like when we used >>= to feed monadic values to lambdas. The last monadic value in a do expression, like Just (show x ++ y) here, can’t be used with <- to bind its result, because that wouldn’t make sense if we translated the do expression back to a chain of >>= applications. Rather, its result is the result of the whole glued up monadic value, taking into account the possible failure of any of the previous ones.

For instance, examine the following line:

*Main> Just 9 >>= (\x -> Just (x > 8))
Just True

Because the left parameter of >>= is a Just value, the lambda is applied to 9 and the result is a Just True. If we rewrite this in do notation, we get:

marySue.hs

marySue :: Maybe Bool
marySue = do
  x <- Just 9 Just (x > 8)
*Main> :l marySue
[1 of 1] Compiling Main             ( marySue.hs, interpreted )
Ok, modules loaded: Main.
*Main> marySue
Just True

If we compare these two, it’s easy to see why the result of the whole monadic value is the result of the last monadic value in the do expression with all the previous ones chained into it.

Our tightwalker’s routine [post precedente] can also be expressed with do notation. landLeft and landRight take a number of birds and a pole and produce a pole wrapped in a Just, unless the tightwalker slips, in which case a Nothing is produced. We used >>= to chain successive steps because each one relied on the previous one and each one had an added context of possible failure. Here’s two birds landing on the left side, then two birds landing on the right and then one bird landing on the left:

routine :: Maybe Pole
routine = do
    start <- return (0,0)
    first <- landLeft 2 start
    second <- landRight 2 first
    landLeft 1 second

Devo caricare le definizioni dal post precedente, ecco il file routine.hs:

routine.hs

type Birds = Int
type Pole = (Birds,Birds)

landLeft :: Birds -> Pole -> Maybe Pole
landLeft n (left,right)
  | abs ((left + n) - right) < 4 = Just (left + n, right) | otherwise = Nothing landRight :: Birds -> Pole -> Maybe Pole
landRight n (left,right)
  | abs (left - (right + n)) < 4 = Just (left, right + n)
  | otherwise                    = Nothing

routine :: Maybe Pole
routine = do
    start <- return (0,0)
    first <- landLeft 2 start
    second <- landRight 2 first
    landLeft 1 second

Let’s see if he succeeds:

*Main> :l routine
[1 of 1] Compiling Main             ( routine.hs, interpreted )
Ok, modules loaded: Main.
*Main> routine
Just (3,2)

He does! Great. When we were doing these routines by explicitly writing >>=, we usually said something like return (0,0) >>= landLeft 2, because landLeft 2 is a function that returns a Maybe value. With do expressions however, each line must feature a monadic value. So we explicitly pass the previous Pole to the landLeft and landRight functions. If we examined the variables to which we bound our Maybe values, start would be (0,0), first would be (2,0) and so on.

Because do expressions are written line by line, they may look like imperative code to some people. But the thing is, they’re just sequential, as each value in each line relies on the result of the previous ones, along with their contexts (in this case, whether they succeeded or failed).

Again, let’s take a look at what this piece of code would look like if we hadn’t used the monadic aspects of Maybe:

routine :: Maybe Pole
routine =
  case Just (0,0) of
    Nothing -> Nothing
    Just start -> case landLeft 2 start of
      Nothing -> Nothing
      Just first -> case landRight 2 first of
        Nothing -> Nothing
        Just second -> landLeft 1 second

See how in the case of success, the tuple inside Just (0,0) becomes start, the result of landLeft 2 start becomes first, etc.

If we want to throw the Pierre a banana peel in do notation, we can do the following:

routine :: Maybe Pole
routine = do
  start <- return (0,0)
  first <- landLeft 2 start
  Nothing
  second <- landRight 2 first
  landLeft 1 second

When we write a line in do notation without binding the monadic value with <-, it’s just like putting >> after the monadic value whose result we want to ignore. We sequence the monadic value but we ignore its result because we don’t care what it is and it’s prettier than writing _ <- Nothing, which is equivalent to the above.

When to use do notation and when to explicitly use >>= is up to you. I think this example lends itself to explicitly writing >>= because each step relies specifically on the result of the previous one. With do notation, we had to specifically write on which pole the birds are landing, but every time we used that came directly before. But still, it gave us some insight into do notation.

In do notation, when we bind monadic values to names, we can utilize pattern matching, just like in let expressions and function parameters. Here’s an example of pattern matching in a do expression:

justH :: Maybe Char
justH = do
  (x:xs) <- Just "hello"
  return x

We use pattern matching to get the first character of the string "hello" and then we present it as the result. So justH evaluates to Just 'h'.

What if this pattern matching were to fail? When matching on a pattern in a function fails, the next pattern is matched. If the matching falls through all the patterns for a given function, an error is thrown and our program crashes. On the other hand, failed pattern matching in let expressions results in an error being produced right away, because the mechanism of falling through patterns isn’t present in let expressions. When pattern matching fails in a do expression, the fail function is called. It’s part of the Monad type class and it enables failed pattern matching to result in a failure in the context of the current monad instead of making our program crash. Its default implementation is this:

fail :: (Monad m) => String -> m a
fail msg = error msg

So by default it does make our program crash, but monads that incorporate a context of possible failure (like Maybe) usually implement it on their own. For Maybe, its implemented like so:

fail _ = Nothing

It ignores the error message and makes a Nothing. So when pattern matching fails in a Maybe value that’s written in do notation, the whole value results in a Nothing. This is preferable to having our program crash. Here’s a do expression with a pattern that’s bound to fail:

wopwop.hs

wopwop :: Maybe Char
wopwop = do
  (x:xs) <- Just ""
  return x

The pattern matching fails, so the effect is the same as if the whole line with the pattern was replaced with a Nothing. Let’s try this out:

*Main> :l wopwop
[1 of 1] Compiling Main             ( wopwop.hs, interpreted )
Ok, modules loaded: Main.
*Main> wopwop
Nothing

The failed pattern matching has caused a failure within the context of our monad instead of causing a program-wide failure, which is pretty neat.

🤣

Haskell – 115 – un po’ di monadi – 3

Continuo da qui, copio qui.

Il caso di Pierre per tenersi bilanciato
Quando Miran racconta storielle mi mette in difficoltà 😐

Now that we know how to feed a Maybe a value to a function of type a -> Maybe b while taking into account the context of possible failure, let’s see how we can use >>= repeatedly to handle computations of several Maybe a values.

Pierre has decided to take a break from his job at the fish farm and try tightrope walking. He’s not that bad at it, but he does have one problem: birds keep landing on his balancing pole! They come and they take a short rest, chat with their avian friends and then take off in search of breadcrumbs. This wouldn’t bother him so much if the number of birds on the left side of the pole was always equal to the number of birds on the right side. But sometimes, all the birds decide that they like one side better and so they throw him off balance, which results in an embarrassing tumble for Pierre (he’s using a safety net).

Let’s say that he keeps his balance if the number of birds on the left side of the pole and on the right side of the pole is within three. So if there’s one bird on the right side and four birds on the left side, he’s okay. But if a fifth bird lands on the left side, then he loses his balance and takes a dive.

We’re going to simulate birds landing on and flying away from the pole and see if Pierre is still at it after a certain number of birdy arrivals and departures. For instance, we want to see what happens to Pierre if first one bird arrives on the left side, then four birds occupy the right side and then the bird that was on the left side decides to fly away.

We can represent the pole with a simple pair of integers. The first component will signify the number of birds on the left side and the second component the number of birds on the right side:

type Birds = Int
type Pole = (Birds,Birds)

First we made a type synonym for Int, called Birds, because we’re using integers to represent how many birds there are. And then we made a type synonym (Birds,Birds) and we called it Pole (not to be confused with a person of Polish descent).

Next up, how about we make a function that takes a number of birds and lands them on one side of the pole. Here are the functions:

pole.hs

type Birds = Int
type Pole = (Birds,Birds)

landLeft :: Birds -> Pole -> Pole
landLeft n (left,right) = (left + n,right)

landRight :: Birds -> Pole -> Pole
landRight n (left,right) = (left,right + n)

Pretty straightforward stuff. Let’s try them out:

Prelude> :l pole
[1 of 1] Compiling Main             ( pole.hs, interpreted )
Ok, modules loaded: Main.
*Main> landLeft 2 (0,0)
(2,0)
*Main> landRight 1 (1,2)
(1,3)
*Main> landRight (-1) (1,2)
(1,1)

To make birds fly away we just had a negative number of birds land on one side. Because landing a bird on the Pole returns a Pole, we can chain applications of landLeft and landRight:

*Main> landLeft 2 (landRight 1 (landLeft 1 (0,0)))
(3,1)

When we apply the function landLeft 1 to (0,0) we get (1,0). Then, we land a bird on the right side, resulting in (1,1). Finally two birds land on the left side, resulting in (3,1). We apply a function to something by first writing the function and then writing its parameter, but here it would be better if the pole went first and then the landing function. If we make a function like this:

*Main> x -: f = f x

We can apply functions by first writing the parameter and then the function:

*Main> 100 -: (*3)
300
*Main> True -: not
False
*Main> (0,0) -: landLeft 2
(2,0)

By using this, we can repeatedly land birds on the pole in a more readable manner:

*Main> (0,0) -: landLeft 1 -: landRight 1 -: landLeft 2
(3,1)

Pretty cool! This example is equivalent to the one before where we repeatedly landed birds on the pole, only it looks neater. Here, it’s more obvious that we start off with (0,0) and then land one bird one the left, then one on the right and finally two on the left.

So far so good, but what happens if 10 birds land on one side?

*Main> landLeft 10 (0,3)
(10,3)

10 birds on the left side and only 3 on the right? That’s sure to send poor Pierre falling through the air! This is pretty obvious here but what if we had a sequence of landings like this:

*Main> (0,0) -: landLeft 1 -: landRight 4 -: landLeft (-1) -: landRight (-2)
(0,2)

It might seem like everything is okay but if you follow the steps here, you’ll see that at one time there are 4 birds on the right side and no birds on the left! To fix this, we have to take another look at our landLeft and landRight functions. From what we’ve seen, we want these functions to be able to fail. That is, we want them to return a new pole if the balance is okay but fail if the birds land in a lopsided manner. And what better way to add a context of failure to value than by using Maybe! Let’s rework these functions:

pole-r.hs

type Birds = Int
type Pole = (Birds,Birds)

landLeft :: Birds -> Pole -> Maybe Pole
landLeft n (left,right)
  | abs ((left + n) - right) < 4 = Just (left + n, right) 
  | otherwise = Nothing landRight :: Birds -> Pole -> Maybe Pole
landRight n (left,right)
  | abs (left - (right + n)) < 4 = Just (left, right + n)
  | otherwise                    = Nothing

Instead of returning a Pole these functions now return a Maybe Pole. They still take the number of birds and the old pole as before, but then they check if landing that many birds on the pole would throw Pierre off balance. We use guards to check if the difference between the number of birds on the new pole is less than 4. If it is, we wrap the new pole in a Just and return that. If it isn’t, we return a Nothing, indicating failure.

Let’s give these babies a go:

*Main> :l pole-r
[1 of 1] Compiling Main             ( pole-r.hs, interpreted )
Ok, modules loaded: Main.
*Main> landLeft 2 (0,0)
Just (2,0)
*Main> landLeft 10 (0,3)
Nothing

Nice! When we land birds without throwing Pierre off balance, we get a new pole wrapped in a Just. But when many more birds end up on one side of the pole, we get a Nothing. This is cool, but we seem to have lost the ability to repeatedly land birds on the pole. We can’t do landLeft 1 (landRight 1 (0,0)) anymore because when we apply landRight 1 to (0,0), we don’t get a Pole, but a Maybe Pole. landLeft 1 takes a Pole and not a Maybe Pole.

We need a way of taking a Maybe Pole and feeding it to a function that takes a Pole and returns a Maybe Pole. Luckily, we have >>=, which does just that for Maybe. Let’s give it a go:

*Main> landRight 1 (0,0) >>= landLeft 2
Just (2,1)

Remember, landLeft 2 has a type of Pole -> Maybe Pole. We couldn’t just feed it the Maybe Pole that is the result of landRight 1 (0,0), so we use >>= to take that value with a context and give it to landLeft 2. >>= does indeed allow us to treat the Maybe value as a value with context because if we feed a Nothing into landLeft 2, the result is Nothing and the failure is propagated:

*Main> Nothing >>= landLeft 2
Nothing

With this, we can now chain landings that may fail because >>= allows us to feed a monadic value to a function that takes a normal one.

Here’s a sequence of birdy landings:

*Main> return (0,0) >>= landRight 2 >>= landLeft 2 >>= landRight 2
Just (2,4)

At the beginning, we used return to take a pole and wrap it in a Just. We could have just applied landRight 2 to (0,0), it would have been the same, but this way we can be more consistent by using >>= for every function. Just (0,0) gets fed to landRight 2, resulting in Just (0,2). This, in turn, gets fed to landLeft 2, resulting in Just (2,2), and so on.

Remember this example from before we introduced failure into Pierre’s routine:

*Main> (0,0) -: landLeft 1 -: landRight 4 -: landLeft (-1) -: landRight (-2)
(0,2)

Nota: funziona solo con la definizione vecchia, Miran lo dice ma ci ho messo un po’ a capirlo.

It didn’t simulate his interaction with birds very well because in the middle there his balance was off but the result didn’t reflect that. But let’s give that a go now by using monadic application (>>=) instead of normal application:

*Main> return (0,0) >>= landLeft 1 >>= landRight 4 >>= landLeft (-1) >>= landRight (-2)
Nothing

Awesome. The final result represents failure, which is what we expected. Let’s see how this result was obtained. First, return puts (0,0) into a default context, making it a Just (0,0). Then, Just (0,0) >>= landLeft 1 happens. Since the Just (0,0) is a Just value, landLeft 1 gets applied to (0,0), resulting in a Just (1,0), because the birds are still relatively balanced. Next, Just (1,0) >>= landRight 4 takes place and the result is Just (1,4) as the balance of the birds is still intact, although just barely. Just (1,4) gets fed to landLeft (-1). This means that landLeft (-1) (1,4) takes place. Now because of how landLeft works, this results in a Nothing, because the resulting pole is off balance. Now that we have a Nothing, it gets fed to landRight (-2), but because it’s a Nothing, the result is automatically Nothing, as we have nothing to apply landRight (-2) to.

We couldn’t have achieved this by just using Maybe as an applicative. If you try it, you’ll get stuck, because applicative functors don’t allow for the applicative values to interact with each other very much. They can, at best, be used as parameters to a function by using the applicative style. The applicative operators will fetch their results and feed them to the function in a manner appropriate for each applicative and then put the final applicative value together, but there isn’t that much interaction going on between them. Here, however, each step relies on the previous one’s result. On every landing, the possible result from the previous one is examined and the pole is checked for balance. This determines whether the landing will succeed or fail.

We may also devise a function that ignores the current number of birds on the balancing pole and just makes Pierre slip and fall. We can call it banana:

banana :: Pole -> Maybe Pole
banana _ = Nothing

Now we can chain it together with our bird landings. It will always cause our walker to fall, because it ignores whatever’s passed to it and always returns a failure. Check it (nota: aggiungo la funzione banana al file pole-r.hs salvando il file come banana.hs):

*Main> :l banana
[1 of 1] Compiling Main             ( banana.hs, interpreted )
Ok, modules loaded: Main.
*Main> return (0,0) >>= landLeft 1 >>= banana >>= landRight 1
Nothing

The value Just (1,0) gets fed to banana, but it produces a Nothing, which causes everything to result in a Nothing. How unfortunate!

Instead of making functions that ignore their input and just return a predetermined monadic value, we can use the >> function, whose default implementation is this:

(>>) :: (Monad m) => m a -> m b -> m b
m >> n = m >>= \_ -> n

Normally, passing some value to a function that ignores its parameter and always just returns some predetermined value would always result in that predetermined value. With monads however, their context and meaning has to be considered as well. Here’s how >> acts with Maybe:

*Main> Nothing >> Just 3
Nothing
*Main> Just 3 >> Just 4
Just 4
*Main> Just 3 >> Nothing
Nothing

If you replace >> with >>= \_ ->, it’s easy to see why it acts like it does.

We can replace our banana function in the chain with a >> and then a Nothing:

*Main> return (0,0) >>= landLeft 1 >> Nothing >>= landRight 1
Nothing

There we go, guaranteed and obvious failure!

It’s also worth taking a look at what this would look like if we hadn’t made the clever choice of treating Maybe values as values with a failure context and feeding them to functions like we did. Here’s how a series of bird landings would look like:

routine :: Maybe Pole
routine = case landLeft 1 (0,0) of
  Nothing -> Nothing
  Just pole1 -> case landRight 4 pole1 of
    Nothing -> Nothing
    Just pole2 -> case landLeft 2 pole2 of
      Nothing -> Nothing
      Just pole3 -> landLeft 1 pole3

We land a bird on the left and then we examine the possibility of failure and the possibility of success. In the case of failure, we return a Nothing. In the case of success, we land birds on the right and then do the same thing all over again. Converting this monstrosity into a neat chain of monadic applications with >>= is a classic example of how the Maybe monad saves us a lot of time when we have to successively do computations that are based on computations that might have failed.

Notice how the Maybe implementation of >>= features exactly this logic of seeing if a value is Nothing and if it is, returning a Nothing right away and if it isn’t, going forward with what’s inside the Just.

In this section, we took some functions that we had and saw that they would work better if the values that they returned supported failure. By turning those values into Maybe values and replacing normal function application with >>=, we got a mechanism for handling failure pretty much for free, because >>= is supposed to preserve the context of the value to which it applies functions. In this case, the context was that our values were values with failure and so when we applied functions to such values, the possibility of failure was always taken into account.

😊

Haskell – 114 – un po’ di monadi – 2

Continuo da qui, copio qui.

La type class Monad
Just like functors have the Functor type class and applicative functors have the Applicative type class, monads come with their own type class: Monad! Wow, who would have thought? This is what the type class looks like:

class Monad m where
  return :: a -> m a

  (>>=) :: m a -> (a -> m b) -> m b

  (>>) :: m a -> m b -> m b
  x >> y = x >>= \_ -> y

  fail :: String -> m a
  fail msg = error msg

Let’s start with the first line. It says class Monad m where. But wait, didn’t we say that monads are just beefed up applicative functors? Shouldn’t there be a class constraint in there along the lines of class (Applicative m) = > Monad m where so that a type has to be an applicative functor first before it can be made a monad? Well, there should, but when Haskell was made, it hadn’t occured to people that applicative functors are a good fit for Haskell so they weren’t in there. But rest assured, every monad is an applicative functor, even if the Monad class declaration doesn’t say so.

The first function that the Monad type class defines is return. It’s the same as pure, only with a different name. Its type is (Monad m) => a -> m a. It takes a value and puts it in a minimal default context that still holds that value. In other words, it takes something and wraps it in a monad. It always does the same thing as the pure function from the Applicative type class, which means we’re already acquainted with return. We already used return when doing I/O. We used it to take a value and make a bogus I/O action that does nothing but yield that value. For Maybe it takes a value and wraps it in a Just.

Just a reminder: return is nothing like the return that’s in most other languages. It doesn’t end function execution or anything, it just takes a normal value and puts it in a context.

The next function is >>=, or bind. It’s like function application, only instead of taking a normal value and feeding it to a normal function, it takes a monadic value (that is, a value with a context) and feeds it to a function that takes a normal value but returns a monadic value.

Next up, we have >>. We won’t pay too much attention to it for now because it comes with a default implementation and we pretty much never implement it when making Monad instances.

The final function of the Monad type class is fail. We never use it explicitly in our code. Instead, it’s used by Haskell to enable failure in a special syntactic construct for monads that we’ll meet later. We don’t need to concern ourselves with fail too much for now.

Now that we know what the Monad type class looks like, let’s take a look at how Maybe is an instance of Monad!

instance Monad Maybe where
  return x = Just x
  Nothing >>= f = Nothing
  Just x >>= f  = f x
  fail _ = Nothing

return is the same as pure, so that one’s a no-brainer. We do what we did in the Applicative type class and wrap it in a Just.

The >>= function is the same as our applyMaybe. When feeding the Maybe a to our function, we keep in mind the context and return a Nothing if the value on the left is Nothing because if there’s no value then there’s no way to apply our function to it. If it’s a Just we take what’s inside and apply f to it.

We can play around with Maybe as a monad:

Prelude> return "WHAT" :: Maybe String
Just "WHAT"
Prelude> Just 9 >>= \x -> return (x*10)
Just 90
Prelude> Nothing >>= \x -> return (x*10)
Nothing

Nothing new or exciting on the first line since we already used pure with Maybe and we know that return is just pure with a different name. The next two lines showcase >>= a bit more.

Notice how when we fed Just 9 to the function \x -> return (x*10), the x took on the value 9 inside the function. It seems as though we were able to extract the value from a Maybe without pattern-matching. And we still didn’t lose the context of our Maybe value, because when it’s Nothing, the result of using >>= will be Nothing as well.

Pausa prima di iniziare un argomento lungo 😋

🤣

Visto nel Web – 325

Lavori in corso, un po’ per volta, intanto ecco cosa ho wisto nel Web 🤣


Emacs features that use regular expressions
#:linguaggi di programmazione
::: John D. Cook

Tens of thousands of celebrities, businesspeople, musicians, models, porn stars and ‘influencers’ bought millions of fake Twitter followers, some of which had stolen the identities of real people
#:social media #:frodi
::: Rich_Harris ::: nickconfessore ::: nickconfessore

A 15-Year-Old Convinced Verizon He Was the Head of the CIA
#:sicurezza, spionaggio, virus
::: Slashdot

Elixir 1.6
#:programmazione funzionale
::: Grab the Blaster

Twitter released Russian Bot Stats (Sept 1 – Nov 15, 2016
#:caos informativo, fake news, bufale
::: krassenstein

Eta’s new look. We’ve rebranded with a new website
#:programmazione funzionale
::: jyothsnasrin

Perché non condividere materiale free sui software di grafica, modellazione e render? Ecco il database di risorse!
#:open source
::: irriverender

Slides for my GTK+ 4 status update
#:programming, codice, snippet
::: matthias_clasen

Linear Haskell: Practical linearity in a higher-order polymorphic language
#:programmazione funzionale
::: b3h3m0th

The reason it’s called a “patch”
#:storia
::: Bill_Gross

Trump Team Considers Nationalizing America’s 5G Network
#:Web, Internet #:censura #:sicurezza, spionaggio, virus
::: Slashdot ::: Slashdot

Tech Giants Brace for Europe’s New Data Privacy Rules
#:sicurezza, spionaggio, virus
::: marcelsalathe

Linus Finally Releases Linux 4.15 Kernel, Blames Intel For Delay
#:sistemi operativi
::: Slashdot

La psicosi degli account fake su Twitter
#:social media #:caos informativo, fake news, bufale
::: DavidPuente

Come educare l’algoritmo di Facebook alle nostre esigenze informative
perso: tanto lo frequento sempre meno
#:social media
::: valigiablu

CopperheadOS: Security features, installing apps, and more
#:sistemi operativi #:dispositivi mobili
::: lucaciavatta

2018 Developer Skills Report
#:programming, codice, snippet
::: nicolaiarocci

Intel Told Chinese Firms of Meltdown Flaws Before the US Government
#:ditte
::: Slashdot

semplicissimo e fantasticissimo #coding #scratch #AR
#:scuola, educazione
::: fulcorno

Competition drives innovation, and pushes businesses forward But there’s nothing quite so impactful as harnessing the collective genius of the #community of #developers – and that’s what #openSource enables
#:open source #:storia
::: anBenedetti

Important new report on Open Education policies in Europe. As we work on #copyright reform for #education, we believe free access to content fulfils same goals
#:copyright e brevetti
::: communia_eu

Just released version 0.4 of the MovingAI benchmark format parser for Rust
#:linguaggi di programmazione
::: thek3nger

Florida Firm Sells Twitter Followers and Bots That Retweet Celebrities, Executives, and ‘Influencers’
#:social media #:frodi
::: Slashdot

I don’t think this would be possible to implement with any degree of reliability, and would kill anonymous/pseudonymous speech besides. We need a solution to abuse/bot farms, but I don’t think this is it
#:social media #:caos informativo, fake news, bufale
::: darkuncle

Good advice for organizations owning open source projects — when shutting down a project, do the right thing!
#:open source
::: gvanrossum

Parrot 3.11 released!
#:sistemi operativi
::: ParrotSec ::: MariusNestor

La storia dell’app di fitness che ha rivelato la posizione di una base Usa segreta
#:social media
::: RadioProzac ::: Slashdot ::: kevincollier

I’m having fun creating material for some IoT related post. Despite what functional programmers enthusiast think, when you’re dealing with Internet of Things devices you’re literally dealing with objects
#:programming, codice, snippet
::: WebReflection

Cyber-attacco contro l’Olanda, poche ore dopo la notizia che i servizi segreti olandesi avevano infiltrato gli hacker del Cremlino
#:sicurezza, spionaggio, virus
::: davcarretta

One possibility is to treat social media in a manner analogous to tobacco and alcohol
#:social media
::: fabiochiusi

Yes, Your Amazon Echo Is an Ad Machine
#:social media
::: Slashdot

Let’s always tell the full story
#:caos informativo, fake news, bufale
::: OgbeniDipo

after 18 years of small to biggest companies, and few as consultant too, I have SO MANY extra things to talk about, but this is a good starting point
#:programming, codice, snippet
::: WebReflection

The Python Visualization Landscape by Jake VanderPlas
#:linguaggi di programmazione
::: ThePSF

This is terrifying. Having a cookie on their computers set by a 1×1 tracking pixel was used to wrongly accuse 30,000 Turks of treason
#:censura
::: torproject

California would require rules on social media ‘bots’ under new legislation
#:social media
::: fabiochiusi

243 Free EBooks on Design, Data, Software, Web Development and Business
#:open source
::: Donearm

MPEG Founder Says the MPEG Business Model Is Broken
#:economia
::: Slashdot

Delta debugging is a great technique. Before C-Reduce I was able to effectively use delta but I haven’t looked back since when reducing C bug repros
#:programming, codice, snippet
::: jevinskie

Graphics and music tools for game development
#:games
::: lucaciavatta

Dave Richeson

Refreshing old computers with Linux
#:sistemi operativi #:hardware
::: lucaciavatta

This is a must read. If you can’t right now, bookmark then come back to it later: How to fix Facebook—before it fixes us
#:social media
::: nicolaiarocci

Siccome riparte la bambola del controllo dei contenuti sui social media (v. factchecking di Fb)
#:caos informativo, fake news, bufale #:censura
::: tedeschini

The UK’s mass surveillance law has been ruled unlawful by the Court of Appeal, after a long running legal challenge by @tom_watson. This means that the Investigatory Powers Act will have to be changed
#:sicurezza, spionaggio, virus
::: mattburgess1

Replace Your Exploit-Ridden Firmware with Linux
#:bug #:hardware
::: b3h3m0th

LKRG – Linux Kernel Runtime Guard
chissà se serve o se può servire o se…
#:sicurezza, spionaggio, virus
::: b3h3m0th

The case for Numba in community code
#:linguaggi di programmazione
::: mrocklin

Tutorial: Install Ubuntu on a Chromebook
#:sistemi operativi
::: ubuntu

Make your data dance with interactive visualization tools
#:programming, codice, snippet
::: NatureNews

California Senate Defies FCC, Approves Net Neutrality Law
#:Web, Internet
::: Slashdot

One of the major reasons that #Python has been so successful is because it’s an easy language to develop in and understand
#:linguaggi di programmazione
::: randal_olson

Infatti quella parte è qualunquismo puro
#:sistemi operativi
::: MarcoAlici

in fact anonymity has been one of the great tools – for voice & for protection – for dissidents, non-conformists, artists, the vulnerable & the merely curious. this is the wrong way to deal w abuse of platforms.
#:social media #:sicurezza, spionaggio, virus
::: davidakaye

ma scrivi roba in Elixir? Great stuff!
#:programmazione funzionale
::: LorenzoSinisi

Facebook Users Cry ‘Censorship’ After Being Told Which Russian Troll Pages They Liked
#:social media #:sicurezza, spionaggio, virus
::: Slashdot

Design Principles From Functional Programming
#:linguaggi di programmazione
::: sjfloat

Google Play Removed 700,000 Bad Apps In 2017, 70 Percent More Than In 2016
#:sicurezza, spionaggio, virus
::: Slashdot

Study: Twitter cuts into Facebook’s lead on traffic sent to publishers; this month FB sent 2.5 visitors for each one Twitter sent; in Oct ’17, ratio was 4.7:1
#:social media #:economia
::: Techmeme

Just came across this visualization from @nytimes ca. 2010… great use of an interpolation line to indicate passage of time!
#:programming, codice, snippet
::: jakevdp

We’re excited to announce the general availability of #Azure Event Grid
#:tools, componenti software
::: Azure

Shrinking WebAssembly and JavaScript code sizes in Emscripten
#:programming, codice, snippet #:Web, Internet
::: YanJeanLee

Microservices vs. monolith: How to choose
#:Web, Internet
::: lucaciavatta

4 new OpenStack tips and guides
#:Web, Internet
::: lucaciavatta

Code Completion with Statistical Language Models
#:linguaggi di programmazione
::: _wilfredh

Facebook e la lotta alla disinformazione. Dubbi e domande sull’iniziativa
#:caos informativo, fake news, bufale
::: valigiablu

Siamo vittime della profilazione dei monopoli digitali ma nessuno se ne cura, tanto meno la politica
#:dati, raccolta
::: AlessLongo

Article 13 and automated upload filters won’t work. Creators are coming together to protect our freedom of expression online. #FixCopyright
#:copyright e brevetti
::: CreateRefresh

GRUB is the algorithm I proposed in my PhD thesis, a looooong time ago… I am proud to know that some friends have implemented it in Linux!
😯😯😯 💥 😁
#:sistemi operativi
::: glipari

Composable and Compilable Macros: You Want it When?
#:lisp(s)
::: loveapaper

It’s here! LibreOffice 6.0 is now available – and it’s a major step forward for productivity software
#:tools, componenti software
::: libreoffice

LinuxBoot linuxboot.org (Linux as Firmware)
#:sistemi operativi
::: b3h3m0th

Samsung Surpasses Intel To Become the World’s Largest Chipmaker
#:hardware
::: Slashdot

High School Computer Science: Look Ma, No Textbooks!
#:scuola, educazione
::: Slashdot

Today, @EU2018BG proposed to copy/paste the failed German ancillary copyright to the EU level in the #Coreper meeting of member states’ ambassadors
#:copyright e brevetti
::: Senficon

What reality stars can teach us about protecting your privacy
#:sicurezza, spionaggio, virus
::: eilah_tan

Débuter sa carrière dans l’open source
in realtà: Start your open source career
#:open source
::: jacquelinclem

Facebook Really Wants You To Come Back
notato anch’io; notato anche che i giovani quando crescono passano a FB da
#:social media
::: Slashdot

Graydon (creator of Rust and Monotone) has this excellent post discussing the importance of running tests on the code after merge, so the build stays green
#prog
::: _wilfredh

Impressive (if somewhat intimidating) blog post showing how to reason from assembly back to the equivalent C code
#:linguaggi di programmazione
::: _wilfredh

Starting with Gawker and L.A. Weekly, we’re backing up entire news sites that might be threatened by the “billionaire problem,” in which wealthy buyers can erase coverage they dislike
#:Web, Internet
::: FreedomofPress

I’m working through all the potential integer overflow issues that Coverity reports for Linux 4.15.0 this week
#:bug #:sistemi operativi
::: embeddedgus

Minimalist container library in C
#:programming, codice, snippet
::: b3h3m0th

Xerox Cedes Control To Fujifilm, Ending Its Independence
#:ditte
::: Slashdot ::: SteveLohr

CUBA.platform – RAD web framework for enterprise applications
#:linguaggi di programmazione
::: CubaPlatform

How I coined the term ‘open source’
#:free open source software
::: lucaciavatta

From Employee to #Entrepreneur in 10 Steps
#:economia
::: simplygolive

Twitter Notifies 1.4 Million Users of Interaction With Russian Accounts
#:social media
::: Slashdot

Excited to announce the release of pdvega: create beautiful, interactive Vega-Lite plots in Python, using the familiar Pandas visualization API
#:linguaggi di programmazione
::: jakevdp

New factsheet by @gravesmatter, @rasmus_kleis quantifies reach of fake news in France and Italy
#:caos informativo, fake news, bufale
::: Mantzarlis ::: rasmus_kleis

La disgrazia di un giornalismo che riporta nei titoli le dichiarazioni dei politici…
#:media #:social media #:caos informativo, fake news, bufale
::: valigiablu

Server: Racket, my ebook on web devel in @racketlang now has a lower-cost starter edition, to get your feet wet with Racket web programming. The full-stack edition contains everything
#:lisp(s) #:Web, Internet
::: alamajesse

A JavaScript Elevator
#:linguaggi di programmazione
::: WebReflection ::: WebReflection ::: WebReflection

A better Clojure REPL experience
#:lisp(s)
::: bhauman

Edwin Hubble

Why do people use old programming languages instead of new ones?
#:linguaggi di programmazione
::: PaniczGodek

The Glasgow Haskell compiler architecture
vecchio ma mooolto istruttivo
#:programmazione funzionale #:manuali, how to
::: onepaperperday

Apple Begins Selling Refurbished iPhone 7 and 7 Plus Models
#:dispositivi mobili
::: Slashdot

Hacking Team Is Still Alive Thanks to a Mysterious Investor From Saudi Arabia
#:sicurezza, spionaggio, virus
::: accessnow

Identità digitale e sicurezza. Gli adulti più anziani mostrano abitudini migliori in termini di creazione delle #password rispetto alle giovani generazioni
#:sicurezza, spionaggio, virus
::: SergioGridelli

I have not worked at Stack Overflow in any capacity since 2012, but I occasionally dip my toe into meta.stackoverflow.com
#:programming, codice, snippet #:Web, Internet
::: codinghorror

La comunicazione politica sui social in tempo di #elezioni2018. Cala Facebook, sale Twitter. Rimane scarsa l’interazione con gli utenti: il target principale sono i media, non i cittadini
#:social media #:politica
::: SergioGridelli

Apple just reported $285B of cash
#:ditte
::: APompliano

This report (in French) says this leaked document shows Intel began notifying its partners on November 29 of the #Meltdown and #Spectre flaws under a strict non-disclosure agreement. That’s the same day that the Intel CEO sold $11 million in shares
#:bug #:hardware #:economia #:ditte
::: zackwhittaker

New Zero-Day Vulnerability Found In Adobe Flash Player
#:sicurezza, spionaggio, virus
::: Slashdot

I cambiamenti di Facebook, le lamentele degli editori e le nostre libertà
#:social media
::: valigiablu

DuckDuckGo CEO: ‘Google and Facebook Are Watching Our Every Move Online. It’s Time To Make Them Stop’
#:sicurezza, spionaggio, virus
::: Slashdot

Thrilled to announce that my book “Data Science at the Command Line” (@OReillyMedia, 2014) can now be read online for free!
#:programming, codice, snippet
::: jeroenhjanssens

Programming the Linux Framebuffer
#:programming, codice, snippet
::: b3h3m0th

Custom Embedded Linux Distributions
#:sistemi operativi
::: b3h3m0th

Minimal Perfect Hash-Tables in Common Lisp
#:lisp(s)
::: FunctorFact

Firefox 59 Will Stop Websites Snooping on Where You’ve Just Been
#:sicurezza, spionaggio, virus
::: Slashdot

Linux Malware Analysis. Why Homebrew Encryption is Bad
#:sicurezza, spionaggio, virus
::: b3h3m0th

Tractor Hacking: The Farmers Breaking Big Tech’s Repair Monopoly
#:hardware
::: jason_koebler

Worldwide #Smartphone Unit Shipments 2004-2017
#:dispositivi mobili
::: fjeronimo

I’m moving my younger son (8) from applesoft to @racketlang earlier than I did his brother
#:lisp(s) #:scuola, educazione
::: ID_AA_Carmack

Chrome OS Is Almost Ready To Replace Android On Tablets
#:sistemi operativi #:dispositivi mobili
::: Slashdot

‘Fiction is outperforming reality’: how YouTube’s algorithm distorts truth
#:media
::: fabiochiusi

Have you ever wanted to evaluate code from slack?
#:linguaggi di programmazione
::: amasad

How to stop me harvesting credit card numbers and passwords from your site
#:sicurezza, spionaggio, virus
::: nicolaiarocci

How to Check Which Linux Kernel Version You’re Using
#:sistemi operativi
::: dcavedon

A che punto siamo con le traduzioni automatiche?

C’è on teh toobz questo lungo (come c’è da aspettarsi per il sito dell’Atlantic) articolo di DRH  Douglas Hofstadter sulle traduzioni.

Riporta esempi chiari (io riesco a controllare solo il primo) davvero illuminanti. Ci tiene a precisare che non è contro l’intelligenza artificiale di cui uno degli obiettivi fin dall’inizio era stata proprio la traduzione automatica:

Despite my negativism, Google Translate offers a service many people value highly: it effects quick-and-dirty conversions of meaningful passages written in language A into not necessarily meaningful strings of words in language B. As long as the text in language B is somewhat comprehensible, many people feel perfectly satisfied with the end product. If they can “get the basic idea” of a passage in a language they don’t know, they’re happy.
This isn’t what I personally think the word “translation” means, but to some people it’s a great service, and to them it qualifies as translation. Well, I can see what they want, and I understand that they’re happy. Lucky them!

Da sempre la traduzione è una delle mie ossessioni. Quando ero giovane mi capitava sempre (allora scrivevi la relazione a mano in modo chiaro e la segretaria (non mia, dell’ufficio) la batteva a macchina) che per i documenti per la CEE (oggi EU) mi correggeva “Brussels” in “Bruxelles” e pensava tra se che non sapevo neanche come si scrive. (Ecco questa è una frase che nessun programma di traduzione saprebbe tradurre. OK, è anche sbagliata, le parentesi ma non solo).

Qualche tempo fa c’è stato un periodo di scambio di informazioni tra colleghi belgi, olandesi e tedeschi, usando l’inglese. Ma non sempre, per esempio nei programmi c’erano commenti nelle lingue locali, spesso incomprensibili.

Google traduce in modo soddisfacente frasi elementari soggetto-verbo-oggetto e a quella forma bisogna attenersi. Ma non tutti costruiscono le frasi in quell’ordine, anche qui in Europa! Inoltre non conosce le lingue allo stesso modo, OK per inglese, tedesco, ebraico (davvero, la frase risultante sembra sensata anche se ovviamente non sono in grado di verificare). Con le lingue orientali, cinese, giapponese e coreano è più quixotico, proprio come dice Doug. Ma anche il francese a volte gli manca il termine! A me capita di dimenticare le parole e recentemente ho bloccato i lavori per non ricordare “torchio” superando l’impasse solo chiedendo immagini di “pressoir”.

Ovviamente anche noi umani –cioè loro– non sempre ce la fanno, non sempre è possibile. Ricordo che avevo chiesto alla mamma (scozzese) di un mio collega la traduzione di “wannabe” ottenendo come risposta che doveva trattarsi di un refuso tipografico. Ero giovane e ancora non c’era il Web. Ma non è solo quello: i modi di dire e i giochi di parole. Terry Pratchett ne è pieno e i traduttori nostrani a volte vanno troppo di corsa. È capitato anche per la Guida Galattica che da noi è stata pubblicata inizialmente su Urania, rivista eccezionale ma non per i Classici di classe mega-ultra-über-plus. Per contro mi piace citare I Fiori Blu, traduzione di Italo Calvino di Les Fleurs Bleues di Raymond Queneau. Da leggere perché è bello, nelle due lingue perché sono due cose differenti. Bravo Italo! Però aspetta un attimo: il titolo non avrebbe dovuto essere I Fiori Azzurri?

Però non condivido completamente le mie itee (auto-cit.). Doug e Italo hanno a che fare con la letteratura ma c’è altro tra la terra e il cielo (ecco un’altra espressione che non devo usare). Capita che Twitter, via Anne-Sylvie Weinmann, mi cinguetta:

A huge THANK YOU @marcelsalathe for sharing this information. Thanks to #AI, my dream came true. Launching the English version of my series of posts “#BigData: a new form of collective intelligence” initially written in French.

Il bello di Twitter (in realtà del Web) sono i link! Tout se tient, mi verrebbe da dire con Anne-Sylvie: è stato Marcel Salathé a ritwittarmelo.

E Marcel (forse dovrei dire prof o Dr) dice che DeepL it’s not only close to 100% correct, but also expresses itself extremely well.

Sì perché mica c’è solo Google Translate; SYSTRAN ha parecchi nipotini, c’è per esempio Bing Translator che lavora anche con Twitter,

Ho sbirciato ma solo di corsa l’inizio dell’opera di Anne-Sylvie e mi sembra tutto OK; Marcel va di tedesco, per me niente da fare. In entrambi i casi si ammette un intervento manuale di rifinitura –OK, in ogni caso bisogna rileggere prima di pubblicare, due volte.

Resta una questione aperta tra Doug e gli altri due autori|traduttori, dice Doug:

Let me return to that sad image of human translators, soon outdone and outmoded,
gradually turning into nothing but quality controllers and text tweakers. That’s a recipe for mediocrity at best. A serious artist doesn’t start with a kitschy piece of error-ridden bilgewater and then patch it up here and there to produce a work of high art. That’s not the nature of art. And translation is an art.

Sono –secondo me– campi diversi, complementari. Ci sarebbero storie di uso del telefono (nelle zone dove il wi-fi prende) di discorsi tra persone di lingue completamente diverse; peccato che non sia attivo nel Web altrimenti conosco chi potrebbe raccontare di  casi tra il vietnamese (lingua difficile) e il cuneese (ancora più difficile).

Eventualmente, come per il caso di DRH, se non troviamo il Pesce Babele (quello della Guida Galattica) mi sa che dobbiamo contentarci di meno. E anche l’inglese dei non anglofoni spesso… OK, come me.

🤣

Haskell – 113 – un po’ di monadi – 1

Continuo da qui, copio qui.

When we first talked about functors, we saw that they were a useful concept for values that can be mapped over. Then, we took that concept one step further by introducing applicative functors, which allow us to view values of certain data types as values with contexts and use normal functions on those values while preserving the meaning of those contexts.

In this chapter, we’ll learn about monads, which are just beefed up applicative functors, much like applicative functors are only beefed up functors.

When we started off with functors, we saw that it’s possible to map functions over various data types. We saw that for this purpose, the Functor type class was introduced and it had us asking the question: when we have a function of type a -> b and some data type f a, how do we map that function over the data type to end up with f b? We saw how to map something over a Maybe a, a list [a], an IO a etc. We even saw how to map a function a -> b over other functions of type r -> a to get functions of type r -> b. To answer this question of how to map a function over some data type, all we had to do was look at the type of fmap:

fmap :: (Functor f) => (a -> b) -> f a -> f b

And then make it work for our data type by writing the appropriate Functor instance.

Then we saw a possible improvement of functors and said, hey, what if that function a -> b is already wrapped inside a functor value? Like, what if we have Just (*3), how do we apply that to Just 5? What if we don’t want to apply it to Just 5 but to a Nothing instead? Or if we have [(*2),(+4)], how would we apply that to [1,2,3]? How would that work even? For this, the Applicative type class was introduced, in which we wanted the answer to the following type:

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b

We also saw that we can take a normal value and wrap it inside a data type. For instance, we can take a 1 and wrap it so that it becomes a Just 1. Or we can make it into a [1]. Or an I/O action that does nothing and just yields 1. The function that does this is called pure.

Like we said, an applicative value can be seen as a value with an added context. A fancy value, to put it in technical terms. For instance, the character 'a' is just a normal character, whereas Just 'a' has some added context. Instead of a Char, we have a Maybe Char, which tells us that its value might be a character, but it could also be an absence of a character.

It was neat to see how the Applicative type class allowed us to use normal functions on these values with context and how that context was preserved. Observe:

Prelude> (*) <$> Just 2 <*> Just 8
Just 16
Prelude> (++) <$> Just "klingon" <*> Nothing
Nothing
Prelude> (-) <$> [3,4] <*> [1,2,3]
[2,1,0,3,2,1]

So now that we treat them as applicative values, Maybe a values represent computations that might have failed, [a] values represent computations that have several results (non-deterministic computations), IO a values represent values that have side-effects, etc.

Monads are a natural extension of applicative functors and with them we’re concerned with this: if you have a value with a context, m a, how do you apply to it a function that takes a normal a and returns a value with a context? That is, how do you apply a function of type a -> m b to a value of type m a? So essentially, we will want this function:

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

If we have a fancy value and a function that takes a normal value but returns a fancy value, how do we feed that fancy value into the function? This is the main question that we will concern ourselves when dealing with monads. We write m a instead of f a because the m stands for Monad, but monads are just applicative functors that support >>=. The >>= function is pronounced as bind.

When we have a normal value a and a normal function a -> b it’s really easy to feed the value to the function — you just apply the function to the value normally and that’s it. But when we’re dealing with values that come with certain contexts, it takes a bit of thinking to see how these fancy values are fed to functions and how to take into account their behavior, but you’ll see that it’s easy as one two three.

Maybe come monade
Now that we have a vague idea of what monads are about, let’s see if we can make that idea a bit less vague.

Much to no one’s surprise, Maybe is a monad, so let’s explore it a bit more and see if we can combine it with what we know about monads.

Make sure you understand applicatives [qui] at this point. It’s good if you have a feel for how the various Applicative instances work and what kind of computations they represent, because monads are nothing more than taking our existing applicative knowledge and upgrading it.

A value of type Maybe a represents a value of type a with the context of possible failure attached. A value of Just "dharma" means that the string "dharma" is there whereas a value of Nothing represents its absence, or if you look at the string as the result of a computation, it means that the computation has failed.

When we looked at Maybe as a functor, we saw that if we want to fmap a function over it, it gets mapped over the insides if it’s a Just value, otherwise the Nothing is kept because there’s nothing to map it over!

Like this:

Prelude> fmap (++"!") (Just "wisdom")
Just "wisdom!"
Prelude> fmap (++"!") Nothing
Nothing

As an applicative functor, it functions similarly. However, applicatives also have the function wrapped. Maybe is an applicative functor in such a way that when we use <*> to apply a function inside a Maybe to a value that’s inside a Maybe, they both have to be Just values for the result to be a Just value, otherwise the result is Nothing. It makes sense because if you’re missing either the function or the thing you’re applying it to, you can’t make something up out of thin air, so you have to propagate the failure:

Prelude> Just (+3) <*> Just 3
Just 6
Prelude> Nothing <*> Just "greed"
Nothing
Prelude> Just odd <*> Nothing
Nothing

When we use the applicative style to have normal functions act on Maybe values, it’s similar. All the values have to be Just values, otherwise it’s all for Nothing!

Prelude> max <$> Just 3 <*> Just 6
Just 6
Prelude> max <$> Just 3 <*> Nothing
Nothing

And now, let’s think about how we would do >>= for Maybe. Like we said, >>= takes a monadic value, and a function that takes a normal value and returns a monadic value and manages to apply that function to the monadic value. How does it do that, if the function takes a normal value? Well, to do that, it has to take into account the context of that monadic value.

In this case, >>= would take a Maybe a value and a function of type a -> Maybe b and somehow apply the function to the Maybe a. To figure out how it does that, we can use the intuition that we have from Maybe being an applicative functor. Let’s say that we have a function \x -> Just (x+1). It takes a number, adds 1 to it and wraps it in a Just:

Prelude> (\x -> Just (x+1)) 1
Just 2
Prelude> (\x -> Just (x+1)) 100
Just 101

If we feed it 1, it evaluates to Just 2. If we give it the number 100, the result is Just 101. Very straightforward. Now here’s the kicker: how do we feed a Maybe value to this function? If we think about how Maybe acts as an applicative functor, answering this is pretty easy. If we feed it a Just value, take what’s inside the Just and apply the function to it. If give it a Nothing, hmm, well, then we’re left with a function but Nothing to apply it to. In that case, let’s just do what we did before and say that the result is Nothing.

Instead of calling it >>=, let’s call it applyMaybe for now. It takes a Maybe a and a function that returns a Maybe b and manages to apply that function to the Maybe a. Here it is in code:

apMaybe.hs

applyMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
applyMaybe Nothing f  = Nothing
applyMaybe (Just x) f = f x

Okay, now let’s play with it for a bit. We’ll use it as an infix function so that the Maybe value is on the left side and the function on the right:

Prelude> :l apMaybe
[1 of 1] Compiling Main             ( apMaybe.hs, interpreted )
Ok, modules loaded: Main.
*Main> Just 3 `applyMaybe` \x -> Just (x+1)
Just 4
*Main> Just "smile" `applyMaybe` \x -> Just (x ++ " :)")
Just "smile :)"
*Main> Nothing `applyMaybe` \x -> Just (x+1)
Nothing
*Main> Nothing `applyMaybe` \x -> Just (x ++ " :)")
Nothing

In the above example, we see that when we used applyMaybe with a Just value and a function, the function simply got applied to the value inside the Just. When we tried to use it with a Nothing, the whole result was Nothing. What about if the function returns a Nothing? Let’s see:

*Main> Just 3 `applyMaybe` \x -> if x > 2 then Just x else Nothing
Just 3
*Main> Just 1 `applyMaybe` \x -> if x > 2 then Just x else Nothing
Nothing

Just what we expected. If the monadic value on the left is a Nothing, the whole thing is Nothing. And if the function on the right returns a Nothing, the result is Nothing again. This is very similar to when we used Maybe as an applicative and we got a Nothing result if somewhere in there was a Nothing.

It looks like that for Maybe, we’ve figured out how to take a fancy value and feed it to a function that takes a normal value and returns a fancy one. We did this by keeping in mind that a Maybe value represents a computation that might have failed.

You might be asking yourself, how is this useful? It may seem like applicative functors are stronger than monads, since applicative functors allow us to take a normal function and make it operate on values with contexts. We’ll see that monads can do that as well because they’re an upgrade of applicative functors, and that they can also do some cool stuff that applicative functors can’t.

We’ll come back to Maybe in a minute, but first, let’s check out the type class that belongs to monads.

Pausa; finora tutto OK ma le monadi hanno fama di … Chissà 😐

🤩

Haskell – 112 – functors, funtors applicativi e monoids – 11

Continuo da qui, copio qui, scrollare fino a “Using monoids to fold data structures”.

Using monoids to fold data structures
One of the more interesting ways to put monoids to work is to make them help us define folds over various data structures. So far, we’ve only done folds over lists, but lists aren’t the only data structure that can be folded over. We can define folds over almost any data structure. Trees especially lend themselves well to folding.

Because there are so many data structures that work nicely with folds, the Foldable type class was introduced. Much like Functor is for things that can be mapped over, Foldable is for things that can be folded up! It can be found in Data.Foldable and because it export functions whose names clash with the ones from the Prelude, it’s best imported qualified (and served with basil):

Prelude> :set prompt "ghci> "
ghci> import qualified Data.Foldable as F

To save ourselves precious keystrokes, we’ve chosen to import it qualified as F. Alright, so what are some of the functions that this type class defines? Well, among them are foldr, foldl, foldr1 and foldl1. Huh? But we already know these functions, what’s so new about this? Let’s compare the types of Foldable‘s foldr and the foldr from the Prelude to see how they differ:

ghci> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
ghci> :t F.foldr
F.foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b

Ah! So whereas foldr takes a list and folds it up, the foldr from Data.Foldable accepts any type that can be folded up, not just lists! As expected, both foldr functions do the same for lists:

ghci> foldr (*) 1 [1,2,3]
6
ghci> F.foldr (*) 1 [1,2,3]
6

Okay then, what are some other data structures that support folds? Well, there’s the Maybe we all know and love!

ghci> F.foldl (+) 2 (Just 9)
11
ghci> F.foldr (||) False (Just True)
True

But folding over a Maybe value isn’t terribly interesting, because when it comes to folding, it just acts like a list with one element if it’s a Just value and as an empty list if it’s Nothing. So let’s examine a data structure that’s a little more complex then.

Remember the tree data structure from the Making Our Own Types and Typeclasses [qui] chapter? We defined it like this:

data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)

We said that a tree is either an empty tree that doesn’t hold any values or it’s a node that holds one value and also two other trees. After defining it, we made it an instance of Functor and with that we gained the ability to fmap functions over it. Now, we’re going to make it an instance of Foldable so that we get the abilty to fold it up. One way to make a type constructor an instance of Foldable is to just directly implement foldr for it. But another, often much easier way, is to implement the foldMap function, which is also a part of the Foldable type class. The foldMap function has the following type:

foldMap :: (Monoid m, Foldable t) => (a -> m) -> t a -> m

Its first parameter is a function that takes a value of the type that our foldable structure contains (denoted here with a) and returns a monoid value. Its second parameter is a foldable structure that contains values of type a. It maps that function over the foldable structure, thus producing a foldable structure that contains monoid values. Then, by doing mappend between those monoid values, it joins them all into a single monoid value. This function may sound kind of odd at the moment, but we’ll see that it’s very easy to implement. What’s also cool is that implementing this function is all it takes for our type to be made an instance of Foldable. So if we just implement foldMap for some type, we get foldr and foldl on that type for free!

This is how we make Tree an instance of Foldable:

instance F.Foldable Tree where
  foldMap f Empty = mempty
  foldMap f (Node x l r) = F.foldMap f l `mappend`
                           f x           `mappend`
                           F.foldMap f r

We think like this: if we are provided with a function that takes an element of our tree and returns a monoid value, how do we reduce our whole tree down to one single monoid value? When we were doing fmap over our tree, we applied the function that we were mapping to a node and then we recursively mapped the function over the left sub-tree as well as the right one. Here, we’re tasked with not only mapping a function, but with also joining up the results into a single monoid value by using mappend. First we consider the case of the empty tree — a sad and lonely tree that has no values or sub-trees. It doesn’t hold any value that we can give to our monoid-making function, so we just say that if our tree is empty, the monoid value it becomes is mempty.

The case of a non-empty node is a bit more interesting. It contains two sub-trees as well as a value. In this case, we recursively foldMap the same function f over the left and the right sub-trees. Remember, our foldMap results in a single monoid value. We also apply our function f to the value in the node. Now we have three monoid values (two from our sub-trees and one from applying f to the value in the node) and we just have to bang them together into a single value. For this purpose we use mappend, and naturally the left sub-tree comes first, then the node value and then the right sub-tree.

Now that we have a Foldable instance for our tree type, we get foldr and foldl for free! Consider this tree:

testTree = Node 5
            (Node 3
                (Node 1 Empty Empty)
                (Node 6 Empty Empty)
            )
            (Node 9
                (Node 8 Empty Empty)
                (Node 10 Empty Empty)
            )

It has 5 at its root and then its left node is has 3 with 1 on the left and 6 on the right. The root’s right node has a 9 and then an 8 to its left and a 10 on the far right side. With a Foldable instance, we can do all of the folds that we can do on lists (raccolgo tutto in tT.hs):

ghci> :l tT
[1 of 1] Compiling Main             ( tT.hs, interpreted )
Ok, modules loaded: Main.
ghci> F.foldl (+) 0 testTree
42
ghci> F.foldl (*) 1 testTree
64800

And also, foldMap isn’t only useful for making new instances of Foldable; it comes in handy for reducing our structure to a single monoid value. For instance, if we want to know if any number in our tree is equal to 3, we can do this:

ghci> getAny $ F.foldMap (\x -> Any $ x == 3) testTree
True

Here, \x -> Any $ x == 3 is a function that takes a number and returns a monoid value, namely a Bool wrapped in Any. foldMap applies this function to every element in our tree and then reduces the resulting monoids into a single monoid with mappend. If we do this:

ghci> getAny $ F.foldMap (\x -> Any $ x > 15) testTree
False

All of the nodes in our tree would hold the value Any False after having the function in the lambda applied to them. But to end up True, mappend for Any has to have at least one True value as a parameter. That’s why the final result is False, which makes sense because no value in our tree is greater than 15.

We can also easily turn our tree into a list by doing a foldMap with the \x -> [x] function. By first projecting that function onto our tree, each element becomes a singleton list. The mappend action that takes place between all those singleton list results in a single list that holds all of the elements that are in our tree:

ghci> F.foldMap (\x -> [x]) testTree
[1,3,6,5,8,9,10]

What’s cool is that all of these trick aren’t limited to trees, they work on any instance of Foldable.

Prima di passare al capitolo successivo questo va assimilato completamente 😋 ci sto lavorando 😋

🤩

AI, innovazioni e blockchain – 7

Cosa non capita nel Web? Per esempio in questi giorni io ho una connessione che cade continuamente; se non vedete questo post è colpa della rete 😋


La tecnologia non è cosa per le Corti di Giustizia
#:innovazioni, futuro
::: CBlengio

Someone tweeted this photo in another context, but I was curious if current object-recognition programs could identify the dog
#:artificial intelligence
::: MelMitchell1

The World’s First Graphical AI Interface
#:artificial intelligence
::: Slashdot

Artificial Intelligence’s ‘Black Box’ Is Nothing to Fear – “The irony is that compared with human intelligence, A.I. is actually the more transparent of intelligences”
#:artificial intelligence
::: marcelsalathe

Summary of #AI in #Davos2018 #WEF2018 . The snowy mountain town of Davos is filled with heated talks all week long. #AI is certainly a highly popular topic. Here is a brief summary after participating in more than a dozen onstage & countless number of offstage discussions
il rapporto del dr. Fei-Fei è unico! come lei ❤
#:artificial intelligence
::: drfeifei

Engineering addiction, bringing about totalitarian control that not even Huxley and Orwell could have imagined
Soros, quello del gombloddo, nèh!
#:artificial intelligence
::: fabiochiusi ::: la Stampa

An experimental @facebook chatbot asks you personal questions and builds a model of you based on your answers
#:artificial intelligence
::: techreview

Python is just dominating the ML/AI space. How did this happen?
#:artificial intelligence
::: amasad

Published the first post in a series explaining how to use @deeplearnjs and the web shape detection API to do realtime smile detection in the browser
#:Web, Internet #:artificial intelligence
::: jozefmaxted

Simplicity: A New Language for Blockchains
#:blockchain e crypto*
::: Alexintosh

Most of the people have no idea what’s coming in the next decade
#:innovazioni, futuro
::: Alexintosh

“Linux Internals”: The Art Of Symbol Resolution
#:sistemi operativi
::: b3h3m0th

Blockchain strenght is not in being a database! Stop doing that!
#:blockchain e crypto*
::: thek3nger

AI is something new and something that needs to be regulated as there may be extreme risks
#:artificial intelligence
::: Davos ::: Davos

The average bitcoin transaction now uses six times amount of energy used to mansplain cryptocurrencies online each day
#:blockchain e crypto*
::: jesslynnrose

$500 Million Worth of Cryptocurrency Stolen From Japanese Exchange
#:blockchain e crypto*
::: Slashdot

CryptoCribs: A blockchain alternative to Airbnb
#:blockchain e crypto*
::: Donearm

Tesla Employees Say Gigafactory Problems Are Worse Than Know
#:innovazioni, futuro
::: Slashdot

Possible Litecoin and Monero Merger Steps Closer To Reality
#:blockchain e crypto*
::: lucaciavatta

Blockchain’s Broken Promises
#:blockchain e crypto*
::: AlfonsoFuggetta

Car Manufacturers Are Tracking Millions of Cars
#:innovazioni, futuro
::: Slashdot

Deanonymizing Tor: Your Bitcoin Transactions May Come Back To Haunt You
#:blockchain e crypto*
::: Slashdot

Chronological List Of #AI Books To Read
cosigliati anche da Ehud Lamm – @ehud
#:artificial intelligence
::: kdnuggets

Want to catch up on the last 30 years of crypto history in 42 minutes? Watch this presentation from Berkeley
#:blockchain e crypto*
::: lopp

In case you were wondering how “the digital economy” ends
#:innovazioni, futuro
::: evgenymorozov

Erlang is one of the very few concurrent languages from the ’80’s- all the rest were sequential — activities in the real world are concurrent so modelling them in Erlang is easy but not so in sequential languages
#:programmazione funzionale #:storia
::: joeerl

“Linear logic and deep learning”: differentiable programming w/o repeating the mistakes of imperative programming
OK, confesso che non ho ancora aperto il PDF
#:artificial intelligence
::: noelwelsh

Monads are not what they seem (Uncovering the hidden nature of programming concepts)
uh! come il precedente
#:programmazione funzionale
::: Jose_A_Alonso

Meet #EMIEW3! Get to know Hitachi’s customer services #robot, and his thoughts on what the future holds
#:innovazioni, futuro
::: Hitachi_APAC

We understand the world through stories; the ones we tell ourselves, and the ones we tell each other
#:artificial intelligence
::: fchollet

Britain’s first Bitcoin heist as trader forced at gunpoint to transfer cyber currency
#:blockchain e crypto*
::: hikikomorphism

AI System Sorts News Articles By Whether Or Not They Contain Actual Information
#:artificial intelligence
::: Slashdot

There are 100M lines of code in the average modern car. This should terrify any experienced programmer
#:innovazioni, futuro
::: RichRogersIoT

World’s Second Largest Meat Processor Invests In Lab-Grown Meat Startup
kwasy panico
#:innovazioni, futuro
::: Slashdot

Ethereum Startup Vanishes After Seemingly Making $11, Leaves Message: ‘Penis’
#:blockchain e crypto*
::: Slashdot

Great @jacobinmag interview with @poptechworks. Well-designed algos gone awry nonetheless; algos as “empathy overrides”, or ways to “manage the poor so that we do not have to eradicate poverty”. Just so much to think about
#:algoritmi, codice
::: fabiochiusi

Understanding blockchain in few minutes
#:blockchain e crypto*
::: lucaciavatta

These drones can plant 100,000 trees a day
#:innovazioni, futuro
::: marcoscan

Announcing the AI Fund! We have raised $175 million, and will start multiple new businesses that use AI to improve human life
#:artificial intelligence
::: AndrewYNg ::: saranormous ::: AndrewYNg

il video integrale del prof. @Ferdinando1970 al @Meetup Bitcoin Venezia
#:blockchain e crypto*
::: interlogica

US Regulators To Subpoena Crypto Exchange Bitfinex, Tether
#:blockchain e crypto*
::: Slashdot

Le #SmartCity nell’era della #trasformazionedigitale: quale cambiamento di senso per le nostre città? La vision di @stefanoepifani
#:innovazioni, futuro
::: IngeniumTw

The Next Time You Order Room Service, It May Come by Robot
#:innovazioni, futuro
::: Slashdot

Robot Delivery Vans Are Arriving Before Self-Driving Cars
#:innovazioni, futuro
::: Slashdot

Facebook Is Banning Cryptocurrency, ICO Ads
#:blockchain e crypto*
::: Slashdot

Don’t believe that AI or software could be your boss?
#:innovazioni, futuro
::: RichRogersIoT

Legge di Moore, mangia la mia polvere. Le implicazioni di un sequenziatore di DNA _tascabile_ sono impressionanti
#:innovazioni, futuro
::: disinformatico

Think “automatic hate speech detection” sounds too good to be true?
#:artificial intelligence
::: ellanso

BasiIndia Vows To Eliminate Use of Cryptocurrencies in the Countrycs of Monero (XMR) explained in 3 minutes
#:blockchain e crypto*
::: lucaciavatta

Why Tether’s Collapse Would Be Bad For Cryptocurrencies
#:blockchain e crypto*
::: Slashdot

Code alignment issues
#:programming, codice, snippet
::: b3h3m0th

For those who claim that I recommend shitcoins
#:blockchain e crypto*
::: officialmcafee

Wasn’t sure it was a good move – but now… I like it!
#:blockchain e crypto*
::: GoranKrampe

He “understands things”, presumably these things include fax machines and the internet
#:blockchain e crypto*
::: amasad

India Vows To Eliminate Use of Cryptocurrencies in the Country
#:blockchain e crypto*
::: Slashdot

Haskell – 111 – functors, funtors applicativi e monoids – 10

Continuo da qui, copio qui, scrollare fino a “The Ordering monoid”.

Il monoide Ordering
Hey, remember the Ordering type? It’s used as the result when comparing things and it can have three values: LT, EQ and GT, which stand for less than, equal and greater than respectively:

Prelude> 1 `compare` 2
LT
Prelude> 2 `compare` 2
EQ
Prelude> 3 `compare` 2
GT
Prelude> -- ovviamente vale anche
Prelude> compare 3 2
GT

With lists, numbers and boolean values, finding monoids was just a matter of looking at already existing commonly used functions and seeing if they exhibit some sort of monoid behavior. With Ordering, we have to look a bit harder to recognize a monoid, but it turns out that its Monoid instance is just as intuitive as the ones we’ve met so far and also quite useful:

instance Monoid Ordering where
  mempty = EQ
  LT `mappend` _ = LT
  EQ `mappend` y = y
  GT `mappend` _ = GT

The instance is set up like this: when we mappend two Ordering values, the one on the left is kept, unless the value on the left is EQ, in which case the right one is the result. The identity is EQ. At first, this may seem kind of arbitrary, but it actually resembles the way we alphabetically compare words. We compare the first two letters and if they differ, we can already decide which word would go first in a dictionary. However, if the first two letters are equal, then we move on to comparing the next pair of letters and repeat the process.

For instance, if we were to alphabetically compare the words "ox" and "on", we’d first compare the first two letters of each word, see that they are equal and then move on to comparing the second letter of each word. We see that 'x' is alphabetically greater than 'n', and so we know how the words compare. To gain some intuition for EQ being the identity, we can notice that if we were to cram the same letter in the same position in both words, it wouldn’t change their alphabetical ordering. "oix" is still alphabetically greater than and "oin".

It’s important to note that in the Monoid instance for Ordering, x `mappend` y doesn’t equal y `mappend` x. Because the first parameter is kept unless it’s EQ, LT `mappend` GT will result in LT, whereas GT `mappend` LT will result in GT:

Prelude> LT `mappend` GT
LT
Prelude> GT `mappend` LT
GT
Prelude> mempty `mappend` LT
LT
Prelude> mempty `mappend` GT
GT

OK, so how is this monoid useful? Let’s say you were writing a function that takes two strings, compares their lengths, and returns an Ordering. But if the strings are of the same length, then instead of returning EQ right away, we want to compare them alphabetically. One way to write this would be like so:

lengthCompare :: String -> String -> Ordering
lengthCompare x y = let a = length x `compare` length y
                        b = x `compare` y
                    in  if a == EQ then b else a

We name the result of comparing the lengths a and the result of the alphabetical comparison b and then if it turns out that the lengths were equal, we return their alphabetical ordering.

But by employing our understanding of how Ordering is a monoid, we can rewrite this function in a much simpler manner:

lC.hs

import Data.Monoid

lengthCompare :: String -> String -> Ordering
lengthCompare x y = (length x `compare` length y) `mappend`
                    (x `compare` y)

We can try this out:

Prelude> :l lC
[1 of 1] Compiling Main             ( lC.hs, interpreted )
Ok, modules loaded: Main.
*Main> lengthCompare "zen" "ants"
LT
*Main> lengthCompare "zen" "ant"
GT

Remember, when we use mappend, its left parameter is always kept unless it’s EQ, in which case the right one is kept. That’s why we put the comparison that we consider to be the first, more important criterion as the first parameter. If we wanted to expand this function to also compare for the number of vowels and set this to be the second most important criterion for comparison, we’d just modify it like this:

lC1.hs

import Data.Monoid

lengthCompare :: String -> String -> Ordering
lengthCompare x y = (length x `compare` length y) `mappend`
                    (vowels x `compare` vowels y) `mappend`
                    (x `compare` y)
    where vowels = length . filter (`elem` "aeiou")

We made a helper function, which takes a string and tells us how many vowels it has by first filtering it only for letters that are in the string “aeiou” and then applying length to that.

*Main> :l lC1
[1 of 1] Compiling Main             ( lC1.hs, interpreted )
Ok, modules loaded: Main.
*Main> lengthCompare "zen" "anna"
LT
*Main> lengthCompare "zen" "ana"
LT
*Main> lengthCompare "zen" "ann"
GT

Very cool. Here, we see how in the first example the lengths are found to be different and so LT is returned, because the length of “zen” is less than the length of “anna”. In the second example, the lengths are the same, but the second string has more vowels, so LT is returned again. In the third example, they both have the same length and the same number of vowels, so they’re compared alphabetically and “zen” wins.

The Ordering monoid is very cool because it allows us to easily compare things by many different criteria and put those criteria in an order themselves, ranging from the most important to the least.

Maibe come monoide
Let’s take a look at the various ways that Maybe a can be made an instance of Monoid and what those instances are useful for.

One way is to treat Maybe a as a monoid only if its type parameter a is a monoid as well and then implement mappend in such a way that it uses the mappend operation of the values that are wrapped with Just. We use Nothing as the identity, and so if one of the two values that we’re mappending is Nothing, we keep the other value. Here’s the instance declaration:

instance Monoid a => Monoid (Maybe a) where
  mempty = Nothing
  Nothing `mappend` m = m
  m `mappend` Nothing = m
  Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)

Notice the class constraint. It says that Maybe a is an instance of Monoid only if a is an instance of Monoid. If we mappend something with a Nothing, the result is that something. If we mappend two Just values, the contents of the Justs get mappended and then wrapped back in a Just. We can do this because the class constraint ensures that the type of what’s inside the Just is an instance of Monoid.

*Main> Nothing `mappend` Just "andy"
Just "andy"
*Main> Just LT `mappend` Nothing
Just LT
*Main> Just (Sum 3) `mappend` Just (Sum 4)
Just (Sum {getSum = 7})

This comes in use when you’re dealing with monoids as results of computations that may have failed. Because of this instance, we don’t have to check if the computations have failed by seeing if they’re a Nothing or Just value; we can just continue to treat them as normal monoids.

But what if the type of the contents of the Maybe aren’t an instance of Monoid? Notice that in the previous instance declaration, the only case where we have to rely on the contents being monoids is when both parameters of mappend are Just values. But if we don’t know if the contents are monoids, we can’t use mappend between them, so what are we to do? Well, one thing we can do is to just discard the second value and keep the first one. For this, the First a type exists and this is its definition:

newtype First a = First { getFirst :: Maybe a }
  deriving (Eq, Ord, Read, Show)

We take a Maybe a and we wrap it with a newtype. The Monoid instance is as follows:

instance Monoid (First a) where
  mempty = First Nothing
  First (Just x) `mappend` _ = First (Just x)
  First Nothing `mappend` x = x

Just like we said. mempty is just a Nothing wrapped with the First newtype constructor. If mappend’s first parameter is a Just value, we ignore the second one. If the first one is a Nothing, then we present the second parameter as a result, regardless of whether it’s a Just or a Nothing:

*Main> :l first
[1 of 1] Compiling Main             ( first.hs, interpreted )
Ok, modules loaded: Main.
*Main> getFirst $ First (Just 'a') `mappend` First (Just 'b')
Just 'a'
*Main> getFirst $ First Nothing `mappend` First (Just 'b')
Just 'b'
*Main> getFirst $ First (Just 'a') `mappend` First Nothing
Just 'a'

First is useful when we have a bunch of Maybe values and we just want to know if any of them is a Just. The mconcat function comes in handy:

*Main> getFirst . mconcat . map First $ [Nothing, Just 9, Just 10]
Just 9

If we want a monoid on Maybe a such that the second parameter is kept if both parameters of mappend are Just values, Data.Monoid provides a the Last a type, which works like First a, only the last non-Nothing value is kept when mappending and using mconcat:

*Main> import Data.Monoid
*Main Data.Monoid> :set prompt "ghci> "
ghci> getLast . mconcat . map Last $ [Nothing, Just 9, Just 10]
Just 10
ghci> getLast $ Last (Just "one") `mappend` Last (Just "two")
Just "two"

Pausa 😋

🤩