Рассмотрим следующие типы сигнатур:
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: он использует монадический синтаксический анализ под обложками.
Я делаю что-то неправильно здесь? Я не вижу, как с учетом этого можно построить парсер таким образом. Любые идеи?