• 怎样理解Functor与Monad


    1. 复合函数操作符

    Prelude> :t (.)
    (.) :: (b -> c) -> (a -> b) -> a -> c
    Prelude> (.) ((+) 5) ((*) 2) 4
    13
    

      

    所以(.)操作符的作用,是将4作为参数传递给((*) 2)函数,再将结果传递给((+) 5)函数。

    这就是数学里面的复合函数:

    f(x) = 2x

    g(x) = x + 5

    g(f(x)) = g(2x) = (2x) + 5 = 2x + 5

    g(f(4)) = 2*4 + 5 = 13

     2. Functor

    194 {- | The 'Functor' class is used for types that can be mapped over.
    195 Instances of 'Functor' should satisfy the following laws:
    196 
    197 > fmap id  ==  id
    198 > fmap (f . g)  ==  fmap f . fmap g
    199 
    200 The instances of 'Functor' for lists, 'Data.Maybe.Maybe' and 'System.IO.IO'
    201 satisfy these laws.
    202 -}
    203 
    204 class  Functor f  where
    205     fmap        :: (a -> b) -> f a -> f b
    206 
    207     -- | Replace all locations in the input with the same value.
    208     -- The default definition is @'fmap' . 'const'@, but this may be
    209     -- overridden with a more efficient version.
    210     (<$)        :: a -> f b -> f a
    211     (<$)        =  fmap . const
    

      id是一个函数

    Prelude> :t id
    id :: a -> a
    Prelude> id "Daniel"
    "Daniel"
    Prelude> id 1
    1
    Prelude> id True
    True
    Prelude> id Just "Happy"
    Just "Happy"
    Prelude> id Nothing
    Nothing
    

      Functor是一种typeclass,用来定义一种允许的操作集合,这里是fmap,并且对于fmap提出了需要满足的条件:

    • fmap id == id
    • fmap (f . g) == fmap f . fmap g

    可以视为"交换律"和“分配律”

    Prelude Data.Char> fmap isDigit ((++) ['0'..'9'] ['a'..'f'])
    [True,True,True,True,True,True,True,True,True,True,False,False,False,False,False,False]
    

      

    Prelude Data.Char> :t isDigit
    isDigit :: Char -> Bool
    

      

    fmap不仅可以操作List(此时与List的函数map作用相同),还可以操作比如Maybe

    Prelude Data.Char> fmap isDigit (Just 'a')
    Just False
    Prelude Data.Char> fmap isDigit (Nothing)
    Nothing
    Prelude Data.Char> fmap isDigit (Just '1')
    Just True
    

      

    3. Manod

    Monad与Functor一样,也是用来定义类型可以进行的操作集合。

    Prelude Data.Char> :i Monad
    class Monad m where
      (>>=) :: m a -> (a -> m b) -> m b
      (>>) :: m a -> m b -> m b
      return :: a -> m a
      fail :: String -> m a
      	-- Defined in `GHC.Base'
    instance Monad Maybe -- Defined in `Data.Maybe'
    instance Monad (Either e) -- Defined in `Data.Either'
    instance Monad [] -- Defined in `GHC.Base'
    instance Monad IO -- Defined in `GHC.Base'
    instance Monad ((->) r) -- Defined in `GHC.Base'
    

      

    可以看到,这些操作包括(>>=) (>>) return fail

    (>>)执行两个操作,但是放弃前一个操作的结果

    Prelude Data.Char> :t (>>)
    (>>) :: Monad m => m a -> m b -> m b
    Prelude Data.Char> (>>) "Daniel" "King"
    "KingKingKingKingKingKing"
    

      

    212 
    213 {- | The 'Monad' class defines the basic operations over a /monad/,
    214 a concept from a branch of mathematics known as /category theory/.
    215 From the perspective of a Haskell programmer, however, it is best to
    216 think of a monad as an /abstract datatype/ of actions.
    217 Haskell's @do@ expressions provide a convenient syntax for writing
    218 monadic expressions.
    219 
    220 Minimal complete definition: '>>=' and 'return'.
    221 
    222 Instances of 'Monad' should satisfy the following laws:
    223 
    224 > return a >>= k  ==  k a
    225 > m >>= return  ==  m
    226 > m >>= (x -> k x >>= h)  ==  (m >>= k) >>= h
    227 
    228 Instances of both 'Monad' and 'Functor' should additionally satisfy the law:
    229 
    230 > fmap f xs  ==  xs >>= return . f
    231 
    232 The instances of 'Monad' for lists, 'Data.Maybe.Maybe' and 'System.IO.IO'
    233 defined in the "Prelude" satisfy these laws.
    234 -}
    235 
    236 class  Monad m  where
    237     -- | Sequentially compose two actions, passing any value produced
    238     -- by the first as an argument to the second.
    239     (>>=)       :: forall a b. m a -> (a -> m b) -> m b
    240     -- | Sequentially compose two actions, discarding any value produced
    241     -- by the first, like sequencing operators (such as the semicolon)
    242     -- in imperative languages.
    243     (>>)        :: forall a b. m a -> m b -> m b
    244         -- Explicit for-alls so that we know what order to
    245         -- give type arguments when desugaring
    246 
    247     -- | Inject a value into the monadic type.
    248     return      :: a -> m a
    249     -- | Fail with a message.  This operation is not part of the
    250     -- mathematical definition of a monad, but is invoked on pattern-match
    251     -- failure in a @do@ expression.
    252     fail        :: String -> m a
    253 
    254     {-# INLINE (>>) #-}
    255     m >> k      = m >>= \_ -> k
    256     fail s      = error s
    

      

    (>>=)是将前一个操作的结果作为参数传递给后一个操作,但是注意需要使用return将从a到b的正常转换(a -> b)变成(a -> mb),即(a -> ma)(a - b) = (a -> mb)

    Prelude Data.Char> :t return
    return :: Monad m => a -> m a
    Prelude Data.Char> :t (>>=)
    (>>=) :: Monad m => m a -> (a -> m b) -> m b
    Prelude Data.Char> (>>=) (return ((++) "Daniel" "King")) ((:) 'X')
    "XDanielKing"
    

      

    Prelude Data.Char> (>>=) (return ((++) "Daniel" "King")) ((++) "Hello ")
    "Hello DanielKing"
    

      

    所以(>>=)和return是配合使用的,效果很类似于Unix下的管道操作。

    Monad的设计想法是允许pure的Haskell可以产生一些side effect,或者说除了自身的值以外,可以保存下一些状态信息。

    比如在这里, ((++) "Daniel" "King")的结果就传递给了后面的action,这样就可以用来更新状态信息。

    比较明显的应用是在IO以及Exception Handling上面。


    如果参考数学中的概念,Monad可以被看作是虚数体系,或者是另外一个维度的类型;

    普通的类型与Monad类型之间需要显式地进行转换,

    return : 普通类型转换成Monad类型

    <-:Monad类型转换成普通类型

    IO action都是操作的Monad类型。

    *RecursiveContents Control.Monad Data.Char System.FilePath> :t forM
    forM :: Monad m => [a] -> (a -> m b) -> m [b]
    *RecursiveContents Control.Monad Data.Char System.FilePath> forM "Daniel King" $ ch -> do return (toUpper ch)
    "DANIEL KING"
    

      

  • 相关阅读:
    深入Java虚拟机(4)——网络移动性
    安装ftp碰到的问题及解决方法
    6.设置ListView的Item的高度无效
    hdu1181(变形课)
    ZooKeeper分布式集群部署及问题
    管理线程之创建线程
    Linux系统编程——多线程实现多任务
    Request.Params用法,后台接收httpget参数
    resharper警告 :linq replace with single call to FirstOrDefault
    SQL Prompt几个快捷键
  • 原文地址:https://www.cnblogs.com/long123king/p/3845070.html
Copyright © 2020-2023  润新知