Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在本例中,列表monad是如何工作的?_List_Haskell_Monads_Do Notation - Fatal编程技术网

List 在本例中,列表monad是如何工作的?

List 在本例中,列表monad是如何工作的?,list,haskell,monads,do-notation,List,Haskell,Monads,Do Notation,列表monad有返回x=[x]。那么,为什么在下面的示例中结果不是[([“a”,“b”],[2,3])] >pairs a b=do{x让我们首先分析并重写函数pairs: pairs a b = do { x <- a; y <- b; return (x, y)} 或者以更规范的形式: pairs a b = (>>=) a (\x -> (>>=) b (\y -> return (x, y))) 现在,列表monad定义为: insta

列表monad有
返回x=[x]
。那么,为什么在下面的示例中结果不是
[([“a”,“b”],[2,3])]


>pairs a b=do{x让我们首先分析并重写函数
pairs

pairs a b = do { x <- a; y <- b; return (x, y)}
或者以更规范的形式:

pairs a b = (>>=) a (\x -> (>>=) b (\y -> return (x, y)))
现在,列表monad定义为:

instance Monad [] where
    return x = [x]
    (>>=) xs f = concatMap f xs
所以我们写了:

pairs a b = concatMap (\x -> concatMap (\y -> [(x, y)]) b) a
因此,我们将两个列表
a
b
作为输入,对
a
执行
concatMap
,使用as函数
(\x->concatMap(\y->[(x,y)])b
。在该函数中,我们对
b
执行另一个
concatMap
,使用as函数
\y->[(x,y)]

因此,如果我们使用
对[“a”,“b”][2,3]
进行评估,我们得到:

   pairs ["a", "b"] [2,3]
-> concatMap (\x -> concatMap (\y -> [(x, y)]) [2,3]) ["a", "b"]
-> concatMap (\y -> [("a", y)]) [2,3] ++ concatMap (\y -> [("b", y)]) [2,3]
-> [("a", 2)] ++ [("a", 3)] ++ [("b", 2)] ++ [("b", 3)]
-> [("a", 2), ("a", 3), ("b", 2), ("b", 3)]
总的来说

pairs a b = do { x <- a; y <- b; return (x, y) }  
          = do { x <- a;
                    do { y <- b; 
                            do { return (x, y) }}}
无论对于特定单子而言,
“for…in…do”
“yield”
意味着什么。更正式地说,它是

          = a  >>= (\x ->
                    do { y <- b;                          -- a >>= k  ===
                            do { return (x, y) }})        -- join (k <$> a)
          = join ( (<$> a)                                --  ( a       :: m a
                   (\x ->                                 --    k       ::   a ->   m b
                    do { y <- b;                          --    k <$> a :: m       (m b) )
                            do { return (x, y) }}) )      --            :: m          b
但是对于列表monad,
“For”
意味着
foreach
,因为
返回x=[x]
连接xs=concat xs

-- join :: m (m a) -> m a
-- join :: [] ([] a) -> [] a
-- join :: [[a]] -> [a]
join = concat
所以,

join    [ [a1, a2, a3, ...],
          [b1, b2, b3, ...],
           .....
          [z1, z2, z3, ...] ]
=
        [  a1, a2, a3, ... ,
           b1, b2, b3, ... ,
            .....
           z1, z2, z3, ...  ]
一元绑定满足
ma>=k=join(fmap kma)
其中
ma::ma,k::a->mb
对于
Monad m
。因此对于
fmap=map
的列表,我们有
ma>=k=join(fmap kma)=concat(map kma)=concatMap kma

m >>= k  =  [ a,        = join [ k a,   = join [ [ a1, a2, ... ],  =  [  a1, a2, ... ,
              b,                 k b,            [ b1, b2, ... ],        b1, b2, ... ,
              c,                 k c,            [ c1, c2, ... ],        c1, c2, ... ,
              d,                 k d,            [ d1, d2, ... ],        d1, d2, ... ,
              e,                 k e,            [ e1, e2, ... ],        e1, e2, ... ,
             ... ] >>= k         ...  ]          ...............  ]      ...........   ]
这正是嵌套循环所做的

循环展开是嵌套循环所做的⁄是,嵌套计算是Monad的本质

注意到这一点也很有趣

 join                =                      =   [a1] ++            =  [a1] ++ join
  [ [ a1, a2, ... ],    [ a1, a2, ... ] ++          [a2, ... ] ++         [ [a2, ...],
    [ b1, b2, ... ],    [ b1, b2, ... ] ++     [ b1, b2, ... ] ++      [ b1, b2, ...],
    [ c1, c2, ... ],    [ c1, c2, ... ] ++     [ c1, c2, ... ] ++      [ c1, c2, ...],
    [ d1, d2, ... ],    [ d1, d2, ... ] ++     [ d1, d2, ... ] ++      [ d1, d2, ...],
    [ e1, e2, ... ],    [ e1, e2, ... ] ++     [ e1, e2, ... ] ++      [ e1, e2, ...],
    ............... ]   ...............        ...............         ..............  ]

这是“嵌套循环⁄yield”类比的核心。单子是高阶幺半群,“有什么问题吗?”

因为-列表单子还有一个
(>>=)=concatMap
绑定操作,您隐式地使用它与
(您了解绑定是如何工作的吗?因为
返回
有一个参数
(x,y)
,因此它产生
[(x,y)]
成对=返回
将提供您的期望值。
@chepner(您的意思是
成对=curry返回
)谢谢您的解释。我的困惑是
-- join :: m (m a) -> m a
-- join :: [] ([] a) -> [] a
-- join :: [[a]] -> [a]
join = concat
join    [ [a1, a2, a3, ...],
          [b1, b2, b3, ...],
           .....
          [z1, z2, z3, ...] ]
=
        [  a1, a2, a3, ... ,
           b1, b2, b3, ... ,
            .....
           z1, z2, z3, ...  ]
m >>= k  =  [ a,        = join [ k a,   = join [ [ a1, a2, ... ],  =  [  a1, a2, ... ,
              b,                 k b,            [ b1, b2, ... ],        b1, b2, ... ,
              c,                 k c,            [ c1, c2, ... ],        c1, c2, ... ,
              d,                 k d,            [ d1, d2, ... ],        d1, d2, ... ,
              e,                 k e,            [ e1, e2, ... ],        e1, e2, ... ,
             ... ] >>= k         ...  ]          ...............  ]      ...........   ]
pairs ["a",                                   -- for x in ["a", "b"] do:
       "b"] [2, 3]                            --          for y in [2, 3] do:
=                                             --                     yield (x,y)
      ["a", 
       "b"] >>= (\x-> join (fmap (\y -> return (x,y)) [2, 3]) )
=
      ["a", 
       "b"] >>= (\x-> concat (map (\y -> [ (x,y) ]) [2, 3]) )
=
join [ "a"  &   (\x-> concat ((\y -> [ (x,y) ]) `map` [2, 3]) ),      -- x & f = f x
       "b"  &   (\x-> concat ((\y -> [ (x,y) ]) `map` [2, 3]) ) ]     
=
join [              concat ((\y -> [ ("a",y) ]) `map` [2, 3])  ,    
                    concat ((\y -> [ ("b",y) ]) `map` [2, 3])   ]     
=
join [ concat [ [("a", 2)], [("a", 3)] ] ,    -- for y in [2, 3] do: yield ("a",y)
       concat [ [("b", 2)], [("b", 3)] ] ]    -- for y in [2, 3] do: yield ("b",y)
=
join [        [  ("a", 2) ,  ("a", 3)  ] ,
              [  ("b", 2) ,  ("b", 3)  ] ]
=
     [           ("a", 2) ,  ("a", 3)    ,
                 ("b", 2) ,  ("b", 3)    ]
 join                =                      =   [a1] ++            =  [a1] ++ join
  [ [ a1, a2, ... ],    [ a1, a2, ... ] ++          [a2, ... ] ++         [ [a2, ...],
    [ b1, b2, ... ],    [ b1, b2, ... ] ++     [ b1, b2, ... ] ++      [ b1, b2, ...],
    [ c1, c2, ... ],    [ c1, c2, ... ] ++     [ c1, c2, ... ] ++      [ c1, c2, ...],
    [ d1, d2, ... ],    [ d1, d2, ... ] ++     [ d1, d2, ... ] ++      [ d1, d2, ...],
    [ e1, e2, ... ],    [ e1, e2, ... ] ++     [ e1, e2, ... ] ++      [ e1, e2, ...],
    ............... ]   ...............        ...............         ..............  ]