用<|>运算符了解功能

时间:2019-08-07 00:51:31

标签: list haskell functional-programming concatenation monads

我有以下类型:

newtype Rep f a = Rep { runRep :: String -> f (String, a) }

类型Rep f a是有状态计算,它以String作为初始状态,并产生(String, a)作为计算结果。计算结果包装在函子f中。

Rep的适用实例如下:

instance Monad f => Applicative (Rep f) where 
    pure x = Rep $ \s -> pure (s, x)
    Rep f <*> Rep x = Rep $ \s -> do 
        (s',rf)  <- f s 
        (s'',rx) <- x s'
        return (s'', rf rx)

Rep的Monad实例如下:

instance Monad f => Monad (Rep f) where 
   return x = pure x 
   Rep a >>= f = Rep $ \s -> do
      (s', ya) <- a s
      let (Rep f') = f ya
      (s'', yf) <- f' s'
      pure (s'', yf)

Rep的替代实例如下:

instance (Monad f, Alternative f) => Alternative (Rep f) where 
    empty = Rep (const empty)
    Rep a <|> Rep b = Rep $ \s -> a s <|> b s

我具有以下数据类型和功能:

data TD = Empty | Fol TD TD | Letters [Char] | Str TD
data Res = Nil | Character Char | Cop Res Res | Special [Res]

findmatch :: (Monad f, Alternative f) => TD -> Rep f Res

findmatch (Str a) =
   frontAdd <$> findmatch a <*> findmatch (Str a)
   <|> pure (Special [])
      where
      frontAdd x (Special xs) = Special (x:xs)
      frontAdd _ _ = error "Not possible."

我无法理解上面的功能。函数frontAdd创建一个Special值,其中包含[Res]的列表。 findmatch返回Rep f ResfrontAdd <$> findmatch a <*> findmatch (Str a)行将frontAdd应用于Resfindmatch a返回的findmatch (Str a)

但是,我不确定具有模式匹配的这一行如何工作:frontAdd x (Special xs) = Special (x:xs)。此外,假设函子f[ ]<|>中的frontAdd <$> findmatch a <*> findmatch (Str a) <|> pure (Special [])将如何工作?我知道如果函子fMaybe,那么<|>会做出左偏的选择,但是我不知道<|>是如何专门用于列表的。在文档中指出:

instance Alternative [] where
  empty = []
  (<|>) = (++) -- length xs + length ys = length (xs ++ ys)

串联的工作原理是什么?我是否正确地说frontAdd <$> findmatch a <*> findmatch (Str a)的结果与空白列表串联在一起?

任何见解都会受到赞赏。

1 个答案:

答案 0 :(得分:1)

首先,如果f[],则pure (Special [])[(Special [])],即[Special []]

第二,列表串联是最自然的事情,

  [a, b, c, d, ...]  ++  [p, q, r, s, ...]
==
  [a, b, c, d, ...   ,    p, q, r, s, ...]

(x:xs) ++ ys  =  x : (xs ++ ys)
[]     ++ ys  =             ys

也就是说,

   xs  ++ ys  =  foldr (:) ys xs

因此

  [a, b, c]  <|>  [Special []]
==
  [a, b, c,        Special []]

  []         <|>  [Special []]
==
  [                Special []]

因此,<|> pure (Special [])不与空白列表连接,而是与Special的列表一起包装空白列表。