3

尝试使用 TypeLits 对数据类型进行 JSON 反序列化,但遇到以下问题:

无法将类型“n”与“2”匹配
      'n' 是一个刚性类型变量,由
        test.hs:14:10 处的实例声明
      预期类型:aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser
                       (X n)
        实际类型:aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser
                       (×2)

在以下示例中,在FromJSON实例中一般允许Nat的正确语法如何:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

import GHC.TypeLits
import Data.Aeson
import Control.Monad (mzero)

data X (n :: Nat) where
  A :: Integer -> X 1
  B :: Integer -> X 2

instance FromJSON (X n) where
  parseJSON (Object o) = do
      v <- o .: "val"
      t <- o .: "type"
      case t of
        "a" -> return $ A v
        "b" -> return $ B v
  parseJSON _       = mzero
4

1 回答 1

3

由于您显然无法在编译时知道要反序列化的类型,因此需要将确切的类型隐藏在存在中,然后通过模式匹配恢复。我通常使用泛型Some类型来隐藏幻像类型。

{-# LANGUAGE PolyKinds #-}

data Some (t :: k -> *) where
    Some :: t x -> Some t

现在您可以将实例编写为

instance FromJSON (Some X) where
    parseJSON (Object o) = do
        v <- o .: "val"
        t <- o .: "type"
        case (t :: String) of
          "a" -> return $ Some $ A v
          "b" -> return $ Some $ B v
    parseJSON _       = mzero

但是,您还需要启用FlexibleInstances扩展。

于 2016-12-18T10:25:21.653 回答