第十四章:單位半群和一些有趣的應用函子

夢飛發表於2017-03-04

1.單位半群 Monoid

  • 凡是包含一個二元運算和這個運算對應的單位元的倒數結構都叫做單位半群:結合律和單位元
  • Haskell中使用型別類Monoid來描述這個數學概念

    class Monoid a where
    mempty :: a
    --Identity of mappend
    mappend :: a -> a -> a
    --An associative operation
    
    
    mconcat :: [a] -> a
    mconcat = foldr mappend mempty
    --Fold a list using the monoid
    

    +mappend大多數情況下會作為中綴函式使用

    (<>) :: Monoid a => a -> a -> a
    (<>) = mappend
    
    
    infixr 6 <>
    

    +幾個常用的單位半群:Monoid [a] Monoid Ordering Monoid ()

    +對於常見的數字型別,他們的單位半群定義可能有多種:使用newtype

  • Endo單位半群

    +名字取自自對映 endomorphism,也就是把型別a對映到自身的函式 +引數和返回值型別相同的函式也可以看做單位半群,此時可以選取id函式作為單位元,(.)作為二元運算

    newtype Endo = Endo {appEndo :: a -> a}
    
    
    instance Monoid (Endo a) where
            mempty = Endo id
            Endo f `mappend` Endo g = Endo (f . g)
    
  • 自由單位半群

    +任意一個單位半群都可以構成一個範疇,這個範疇只有一個物體

    +我們把這種從一個物體對映到它自身的態射稱自態射

    +通過構造型別[a]把任意一個型別a變成一個單位半群,只需固定memty=[],mappend =++即可

    +把從一個集合通過建立子集構造出來的單位半群叫自由單位半群 free Monoid

  • 逆 dual

    +“互為相反”

    newtype Dual a = Dual {getDual :: a}
    
    
    instance Monoid a => Monoid (Dual a) where
            mempty = Dual mempty
            Dual x `mappend` Dual y = Dual (y `mappend` x)
    

2.當單位半群遇上應用函子

函子約束的是容器型別( * -> * ),單位半群約束的是實體型別(*).

  • Const a的應用函子例項

    +Const a 在某些情況下可以成為應用函子

    +Const a 無法提供的“最小上下文”,在a是單位半群的時候,可以由a型別對應的mempty提供

    instance Monoid a => Applicative (Const a ) where
        pure _ = Const menmpty
        (Const x) <*> (Const y) = Const (x `mappend` y)
    
  • 選擇應用函子

    +通過Const包裹,可以讓任意一個單位半群成為應用函子

    +對某些應用函子而言,他們恰巧也是單位半群

    class Applicative f => Alternative f where   
        empty :: f a
        (<|>) :: f a -> f a -> f a  | infixl 3 |
    
    
    instance Alternative [] where
        empty = []
        (<|>) = (++)
    
    
    instance Alternative Maybe where
        empty = Nothing
        Nothing <|> r = r
        l       <|> _ = l
    

    +Alternative提供的empty就是在沒有值的情況下函子應該具有的上下文,<|>則提供了連線被函子包裹的值的方法

  • 拉鍊應用函子

    newtype ZipList a = ZipList {getZipList :: [a]}
    
    
    instance Applicative ZipList where
        pure x = ZipList (repeat x)
        ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)
    

相關文章