Рассмотрим следующие типы сигнатур:
data Foo x = Foo {
name :: String
, reader :: String -> x
}
instance Functor Foo where
fmap f (Foo n r) = Foo n $ f . r
Теперь я показываю естественное преобразование от Foo
до optparse-applicative
Parser
type:
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
Учитывая, что это свободный функтор, я должен поднять mkParser
на естественное преобразование от 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
и some
: он использует монадический синтаксический анализ под обложками.
Я делаю что-то неправильно здесь? Я не вижу, как с учетом этого можно построить парсер таким образом. Любые идеи?