简体   繁体   中英

Are Maybe String and Maybe Int both Monoids in Haskell?

I´ve gotten into a bit of confusion whether Maybe Int and Maybe String are both monoids in Haskell because i dont really know what functions you can apply to Int or String in terms of monoids with their neutral element and associativity rules? Can anybody help me out?

The Monoid instance for Maybe types has been defined as [src] :

 instance Semigroup a => Monoid (Maybe a) where mempty = Nothing

it thus requires Int or String to be instances of the Semigroup type class . Since a String is the same as type String = [Char] and thus a list of Char s, this is the case, indeed we see [src] :

 instance Semigroup [a] where (<>) = (++) {-# INLINE (<>) #-} stimes = stimesList

so it will append the two lists, and for a Maybe this means [src] :

 instance Semigroup a => Semigroup (Maybe a) where Nothing <> b = ba <> Nothing = a Just a <> Just b = Just (a <> b) stimes = stimesMaybe

This thus means that for two Maybe String s, the neutral element is Nothing and the binary operator will append the two strings wrapped in Just … data constructors if these are both Just s, the Just one if one of the two is a Just , or Nothing if both items are Nothing s.

This is not the case for an Int , indeed. For integers there can be multiple Monoid instances, for example ⟨ℤ,+, 0⟩ or ⟨ℤ,×, 1⟩.

There is a Monoid instance for any Maybe a as long as a itself has a Monoid instance; the combination of two Just values simply combines the wrapped values according to their instance, while anything combined with Nothing is itself Nothing .

String has a Monoid instance by virtue of being an alias of [Char] ; all lists are monoids via list concatenation with the empty list as the identity. As a result, Maybe String is a monoid as well.

> Just "Fo" <> Just "o"
Just "Foo"
> Just "Fo" <> Nothing
Nothing

Maybe Int is not a monoid, because Int is not a monoid. This is because there are multiple choices for how to make Int a monoid, so no one choice is chosen as special. Instead, several new types are defined with distinct Monoid instances to clarify which operation you want to use.

> import Data.Monoid
> (3 :: Int) <> 5

<interactive>:8:1: error:
    • No instance for (Semigroup Int) arising from a use of ‘<>’
    • In the expression: (3 :: Int) <> 5
      In an equation for ‘it’: it = (3 :: Int) <> 5

-- (+) and 0
> Sum (3 :: Int) <> Sum 5
Sum {getSum = 8}

-- (*) and 1
> Product (3 :: Int) <> Product 5
Product {getProduct = 15}

> Just (Sum (3 :: Int)) <> Just (Sum 5)
Just (Sum {getSum = 8})
> Just (Sum (3 :: Int)) <> Nothing
Nothing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM