Haskell - 变量或函数上的类型签名

时间:2014-11-17 01:52:30

标签: haskell

这是背景,以构建JSON解析器:

  1. 我们有一个数据类型JValue和几个类型构造函数,例如JNumber,它接受​​一个数值并构造一个JValue数据。

    data JValue = JNumber Double deriving (Eq, Ord, Show)
    
  2. 现在我们要构建一个错误处理程序,它可以检查是否可以解析输入参数。这是一个类型类定义:

    type JSONError = String
    class JSON a where
        fromJValue :: JValue -> Either JSONError a
    
  3. 然后实现类JSON的实例:

    instance JSON JValue where
        fromJValue = Right
    
  4. 问题在这里,我想尝试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的含义,我认为作者尝试做的是实施Stringclass JSON JValue实例然后我们可以获得{{1}}的内容。

3 个答案:

答案 0 :(得分:1)

来自我的评论

看看aeson如何实现它,你有

decode :: FromJSON a => ByteString -> Maybe a

每当您以交互方式使用它时,您始终必须将其指定为

decode "{}" :: Maybe MyType

当您在较大的项目中使用fromJValue(或decode)时,大多数时候这些多态值会在某些时候转换为具体的值,因此编译器可以推断出什么要使用的类型,但是当交互使用时,你必须要有一些东西,使得类型具体,然后才能打印出来。此规则有例外,因为GHCi默认为NumIntegral和其他一些,因为没有这些默认设置会出现更多类型错误和混淆。

答案 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