实例未导出?

时间:2014-07-12 16:09:42

标签: haskell

我正在尝试将元组转换为HList.Record并且有一些非常奇怪的东西。 我创建了一个ToRecord类,其中压缩一组事物和一组标签到记录。 一切都在编译,但实例似乎消失了。当我尝试使用它们时,GHC抱怨我要求的实例不存在。

{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

-- standard
import GHC.TypeLits (Symbol)
-- third-party
import Data.HList.FakePrelude
import Data.HList.Record
import Data.HList.Labelable
-- local

-- * Tuples <-> Records Conversion
class ToRecord a b where
    type Result a b :: *
    toRecord :: a -> b -> Result a b -- Result a b

instance  ToRecord (Label t1, Label t2) (v1, v2) where
    type Result (Label t1, Label t2) (v1, v2) = Record '[Tagged (t1) v1, Tagged (t2) v2]
    toRecord (t1, t2) (v1, v2) = t1 .=. v1 .*. t2 .=. v2 .*. emptyRecord

instance  ToRecord (Label t1, Label t2, Label t3) (v1, v2, v3) where
    type Result (Label t1, Label t2, Label t3) (v1, v2, v3) = 
         Record '[Tagged (t1) v1, Tagged (t2) v2, Tagged t3 v3]
    toRecord (t1, t2, t3) (v1, v2, v3) = t1 .=. v1 .*. t2 .=. v2 .*. t3 .=. v3 .*. emptyRecord

-- dummy instance to check GHC behavior
instance ToRecord Char Integer where
    type Result Char Integer = (Char, Integer)
    toRecord c i = (c, i)

value = Label :: Label "value"
name = Label :: Label "name"

test = toRecord  (value, name) (5 :: Int, "age")

错误讯息:

 Utils.hs:34:8:
 No instance for (ToRecord
                    (Label Symbol "value", Label Symbol "name") (Int, [Char]))
   arising from a use of `toRecord'
 Possible fix:
   add an instance declaration for
   (ToRecord
      (Label Symbol "value", Label Symbol "name") (Int, [Char]))
 In the expression: toRecord (value, name) (5 :: Int, "age")
 In an equation for `test':
    test = toRecord (value, name) (5 :: Int, "age")

此外,如果删除test行并将文件加载到GHC中。实例丢失(使用:i ToRecord),只显示虚拟的ToRecod Char Integer

Utils Database.Harehouse.SQLFragment>:i ToRecord
class ToRecord a b where
  type family Result a b :: *
  toRecord :: a -> b -> Result a b
        -- Defined at Database/Harehouse/Utils.hs:15:7
instance ToRecord Char Integer
  -- Defined at Database/Harehouse/Utils.hs:27:10

任何想法(我使用的是GHC 7.6.3)?

1 个答案:

答案 0 :(得分:3)

错误非常明确:编译器推断实例必须是ToRecord (Label Symbol "value", Label Symbol "name") (Int, [Char]),但不存在此类实例。您隐式编写的实例具有另一个参数:参数的类型。在这种情况下,您所拥有的是ToRecord (Label (t1 :: *), Label (t2 :: *)) (v1, v2) - 除非您使用PolyKinds,否则所有多态种类都会成为*。例如:

l0 = Label :: Label Int
l1 = Label :: Label Bool

test = toRecord (l0, l1)  (5 :: Int, "age")

编译就好了。如果您打开PolyKinds,则可以写

instance ToRecord (Label (t1 :: k), Label (t2 :: k)) (v1, v2) where

然后您的示例将起作用:

>toRecord  (value, name) (5 :: Int, "age")
Record{value=5,name="age"}

我无法复制这个问题而某些实例没有显示出来。

澄清言论:

也许我不应该说它很清楚。类型类型的类型是构造函数的参数。 Label实际上有两个参数: type 参数和type参数的。首先写入kind参数 - 因此,您有value :: Label Symbol "value"(符号是一种字符串类型文字)。当然,你不能这样写,但这就是GHC打印它的方式。

种类可以像类型一样推断。默认情况下,推断的类型将为*。在您的代码中,t1中的t2ToRecord (Label t1, Label t2) (v1, v2)类型为*。因此,Label ("value" :: Symbol)Label (t1 :: *)无法统一。

t1 :: kt1 :: Symbol都可以像(f :: Integral a => a -> a) (1 :: Int)(f :: Int -> Int) (1 :: Int)一样工作。您需要KindSignatures扩展名才能写t1 :: Symbol,但KindSignaturesDataKinds隐含PolyKinds

相关问题