这是背景,以构建JSON解析器:
我们有一个数据类型JValue
和几个类型构造函数,例如JNumber
,它接受一个数值并构造一个JValue
数据。
data JValue = JNumber Double deriving (Eq, Ord, Show)
现在我们要构建一个错误处理程序,它可以检查是否可以解析输入参数。这是一个类型类定义:
type JSONError = String
class JSON a where
fromJValue :: JValue -> Either JSONError a
然后实现类JSON的实例:
instance JSON JValue where
fromJValue = Right
问题在这里,我想尝试fromJValue
(JNumber 1)
,JValue
应该是*Main> fromJValue (JNumber 1)
<interactive>:3:1:
No instance for (JSON a0) arising from a use of ‘it’
The type variable ‘a0’ is ambiguous
Note: there is a potential instance available:
instance JSON JValue -- Defined at JSONSubset.hs:8:10
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
类型变量。但是,在ghci,我有这个:
print
根据此错误信息,功能fromJValue (JNumber 1)
无法识别fromJValue
的返回值类型。 这是一个令人困惑的问题:我认为Either JSONError JValue
的结果可以推断为instance JSON JValue
,因为它是fromJValue
的成员。< / p>
注意:关于Int
的含义,我认为作者尝试做的是实施String
或class JSON
JValue
实例然后我们可以获得{{1}}的内容。
答案 0 :(得分:1)
来自我的评论
看看aeson如何实现它,你有
decode :: FromJSON a => ByteString -> Maybe a
每当您以交互方式使用它时,您始终必须将其指定为
decode "{}" :: Maybe MyType
当您在较大的项目中使用fromJValue
(或decode
)时,大多数时候这些多态值会在某些时候转换为具体的值,因此编译器可以推断出什么要使用的类型,但是当交互使用时,你必须要有一些东西,使得类型具体,然后才能打印出来。此规则有例外,因为GHCi默认为Num
,Integral
和其他一些,因为没有这些默认设置会出现更多类型错误和混淆。
答案 1 :(得分:1)
问题是,fromJSON (JValue 1)
类型Either String a
的类型为a
,但您尚未指定a
。 GHC说,它知道一个特定的实例,但它不会假设那是你的意思。
以下是JSON
类型更多可能实例的更多示例:
import qualified Data.ByteString.Char8 as B
-- convert to a Double
instance JSON Double where
fromJValue (JNumber x) = Right x
-- convert to a ByteString
instance JSON B.ByteString where
fromJValue (JNumber x) = Right (B.pack $ show x)
-- convert to an Int
instance JSON Int where
fromJValue (JNumber x) = Left "conversion to Int not supported"
以及使用这些实例的一些示例:
ghci> let j = JNumber 123
ghci> fromJValue j :: Either String B.ByteString
Right "123.0"
ghci> fromJValue j :: Either String Double
Right 123.0
ghci> fromJValue j :: Either String Int
Left "conversion to Int not supported"
如果无法推断a
的类型,则fromJSON j
的解释不明确。
答案 2 :(得分:0)
要编译代码,只需将类定义更改为:
class JSON a where
fromJValue :: a -> Either JSONError a