我有以下类型:
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 Res
。 frontAdd <$> findmatch a <*> findmatch (Str a)
行将frontAdd
应用于Res
和findmatch a
返回的findmatch (Str a)
。
但是,我不确定具有模式匹配的这一行如何工作:frontAdd x (Special xs) = Special (x:xs)
。此外,假设函子f
是[ ]
,<|>
中的frontAdd <$> findmatch a <*> findmatch (Str a) <|> pure (Special [])
将如何工作?我知道如果函子f
是Maybe
,那么<|>
会做出左偏的选择,但是我不知道<|>
是如何专门用于列表的。在文档中指出:
instance Alternative [] where
empty = []
(<|>) = (++) -- length xs + length ys = length (xs ++ ys)
串联的工作原理是什么?我是否正确地说frontAdd <$> findmatch a <*> findmatch (Str a)
的结果与空白列表串联在一起?
任何见解都会受到赞赏。
答案 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
的列表一起包装空白列表。