Resolution of the monoid instance `Int & # 8594; Int & # 8594; Ordering`

I plan to demonstrate an example of the power of classrooms in a short introduction that I will give to Haskell tomorrow.

I thought I would double check what I was going to introduce, because I am not 100% sure.

So let's say I have two functions:

firstSort :: Int -> Int -> Ordering firstSort ab = compare (even a) (even b) secondSort :: Int -> Int -> Ordering secondSort = compare 

Now I can combine these two types thanks to my Monoid instances:

 sort :: Int -> Int -> Ordering sort = firstSort <> secondSort 

Now what I would like to confirm is the process used during the mappend two types.

From what I understand, it works as follows:

  • instance first:

     instance Monoid b => Monoid (a -> b) where mempty _ = mempty mappend fgx = fx `mappend` gx 

    . This is done by creating a this instance using (Int -> Int) . Also, the mappend declaration puzzled me for a while, as it takes 3 arguments instead of 2, but then I remembered that (a -> b) -> (a -> b) -> (a -> b) matches (a -> b) -> (a -> b) -> a -> b .

    Thanks to this instance, we get that firstSort <> secondSort :

     \ab -> (firstSort ab) <> (secondSort ab) 
  • then instance:

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

    used with the specified mappend based on the results of firstSort and secondSort

So, to summarize, it will correspond to the Monoid b => Monoid (a -> b) instance Monoid b => Monoid (a -> b) with b = Ordering and a = (Int -> Int) , and then the Monoid Ordering instance.

Is it correct?

+6
source share
2 answers

Yes. You have finished correctly.

Since Int -> Int -> Ordering is in curry, it can be considered as a function of one argument, which returns another function. I.e:.

 Int -> (Int -> Ordering) 

Therefore, the compiler resolves Monoid instances in three steps:

  Value Type | Monoid Instance --------------------------|--------------------------- Int -> (Int -> Ordering) | instance Monoid b => Monoid (a -> b) Int -> Ordering | instance Monoid b => Monoid (a -> b) Ordering | instance Monoid Ordering 
+7
source

We will see. I don't think the a you need is (Int -> Int) , because function types are associated on the right when there are no brackets. In your case, the types

 firstSort :: Int -> (Int -> Bool) secondSort :: Int -> (Int -> Bool) 

So, something interesting is going on here. When you combine two functions, it actually does it twice! Firstly, a is only the first Int and b is Int -> Bool , so we must use the monoid structure Int -> Bool . But for this we have to repeat the same thing, so a is Int , and b is Bool .

 firstSort <> secondSort = \a -> (firstSort a) <> (secondSort a) = \a -> (\b -> (firstSort ab) <> (secondSort ab)) 

But the end result is still the same as you:

  = \ab -> (firstSort ab) <> (secondSort ab) 
+7
source

All Articles