带有 DataKinds 的 FromJSON 实例
FromJSON instance with DataKinds
尝试使用 TypeLits 对数据类型进行 JSON 反序列化时,我遇到了以下问题:
无法将类型“n”与“2”匹配
‘n’ 是一个严格的类型变量,由
test.hs:14:10 处的实例声明
预期类型:aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser
(Xn)
实际类型:aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser
(X 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
由于您显然无法在编译时知道要反序列化的类型,因此需要将确切的类型隐藏在存在项中,然后通过模式匹配恢复。我通常使用通用 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
扩展程序。
尝试使用 TypeLits 对数据类型进行 JSON 反序列化时,我遇到了以下问题:
无法将类型“n”与“2”匹配 ‘n’ 是一个严格的类型变量,由 test.hs:14:10 处的实例声明 预期类型:aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser (Xn) 实际类型:aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser (X 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
由于您显然无法在编译时知道要反序列化的类型,因此需要将确切的类型隐藏在存在项中,然后通过模式匹配恢复。我通常使用通用 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
扩展程序。