考虑以下类型签名:
data Foo x = Foo {
name :: String
, reader :: String -> x
}
instance Functor Foo where
fmap f (Foo n r) = Foo n $ f . r
Foo
现在我展示了从to类型optparse-applicative
的自然转换Parser
:
import qualified Options.Applicative as CL
mkParser :: Foo a -> CL.Parser a
mkParser (Foo n _) = CL.option CL.disabled ( CL.long n )
(好吧,它有点没用,但它会用于讨论)。
现在我将Bar
成为免费的替代仿函数Foo
:
type Bar a = Alt Foo a
鉴于这是一个自由函子,我应该能够从tomkParser
进行自然转换:Bar
Parser
foo :: String -> (String -> x) -> Bar x
foo n r = liftAlt $ Foo n r
myFoo :: Bar [String]
myFoo = many $ foo "Hello" (\_ -> "Hello")
clFoo :: CL.Parser [String]
clFoo = runAlt mkParser $ myFoo
事实上,这很有效,给了我一个Parser
支持。然而,这是一个非常没用的,因为试图用它做很多事情会导致无限循环。例如,如果我尝试描述它:
CL.cmdDesc clFoo
> Chunk {unChunk =
并挂起直到被打断。
其原因似乎是在其定义中optparse-applicative
作弊many
and some
:它在幕后使用单子解析。
我在这里做错了吗?鉴于此,我不明白如何以这种方式构造解析器。有任何想法吗?