具有专用化规则的功能依赖关系



我想写一个专业化重写规则 ,以便规则仅在输入类型为ByteString时触发。

{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Void
import Text.Megaparsec
import qualified Data.ByteString as B
combin :: forall e s m a. (MonadParsec e s m)
=> m a
-> m a
combin = label "String generic"
combinByteString :: forall e s m a. (MonadParsec e s m, s ~ B.ByteString)
=> m a
-> m a
combinByteString = label "ByteString specialized"
main = do
parseTest (combin empty :: Parsec Void String String) ""
parseTest (combin empty :: Parsec Void B.ByteString String) ""
{-# NOINLINE combin #-}
{-# NOINLINE combinByteString #-}
{-# RULES "combin/ByteString" combin = combinByteString #-}

当我尝试构建它时,它失败了:

$ cabal v2-run
Build profile: -w ghc-8.6.5 -O1
Main.hs:25:40: error:
• Couldn't match type ‘s’ with ‘B.ByteString’
arising from a functional dependency between constraints:
‘MonadParsec e B.ByteString m’
arising from a use of ‘combinByteString’ at Main.hs:25:40-55
‘MonadParsec e s m’
arising from the RULE "combin/ByteString" at Main.hs:25:11-55
‘s’ is a rigid type variable bound by
the RULE "combin/ByteString"
at Main.hs:25:11-55
• In the expression: combinByteString
When checking the transformation rule "combin/ByteString"
|
25 | {-# RULES "combin/ByteString" combin = combinByteString #-}

MonadParsec的输入流类型参数s在功能上依赖于Monad参数m

class (Stream s, MonadPlus m) => MonadParsec e s m | m -> e s where

下面是用于尝试构建的specialize.cabal文件。

cabal-version:       >=1.10
name:                specialize
version:             0.1.0.0
build-type:          Simple
executable specialize
main-is:             Main.hs
build-depends:       base >= 4
,megaparsec
,bytestring
default-language:    Haskell2010

如果成功,输出应如下所示:

1:1:
|
1 | <empty line>
| ^
expecting String generic
1:1:
|
1 | <empty line>
| ^
expecting ByteString specialized

建议?

此规则有效,但仅适用于 GHC 8.8.1,不适用于 GHC 8.6.5。

{-# LANGUAGE TypeApplications #-}
{-# RULES "combin/ByteString" forall e. forall. 
combin @e @B.ByteString = combinByteString @e @B.ByteString
#-}

此规则适用于 GHC 8.6.5 和 8.0.2

{-# RULES "combin/ByteString"
forall (pa :: ParsecT e B.ByteString m a).
combin @e @B.ByteString @(ParsecT e B.ByteString m) @a pa = 
combinByteString @e @B.ByteString @(ParsecT e B.ByteString m) @a pa
#-}

相关内容

  • 没有找到相关文章

最新更新