{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} module Text.LambdaOptions.Internal.OpaqueParser ( OpaqueParser, GetOpaqueParsers(..), ) where import Data.Proxy import Data.Typeable hiding (typeRep) import Text.LambdaOptions.Internal.Opaque import Text.LambdaOptions.Parseable -------------------------------------------------------------------------------- decomposeFuncProxy :: Proxy (a -> b) -> (Proxy a, Proxy b) decomposeFuncProxy _ = (Proxy, Proxy) -------------------------------------------------------------------------------- type OpaqueParser = [String] -> (Maybe Opaque, Int) parseOpaque :: (Parseable a, Typeable a) => Proxy a -> OpaqueParser parseOpaque proxy str = case parse str of (Nothing, n) -> (Nothing, n) (Just x, n) -> (Just $ Opaque $ x `asProxyTypeOf` proxy, n) -------------------------------------------------------------------------------- class GetOpaqueParsers r f | f -> r where getOpaqueParsers :: Proxy f -> [(TypeRep, OpaqueParser)] instance (Parseable a, Typeable a, GetOpaqueParsers r b) => GetOpaqueParsers r (a -> b) where getOpaqueParsers funcProxy = let (proxyA, proxyB) = decomposeFuncProxy funcProxy typeRep = typeOf proxyA parser = parseOpaque proxyA in (typeRep, parser) : getOpaqueParsers proxyB instance (Monad m) => GetOpaqueParsers r (m r) where getOpaqueParsers ~Proxy = []