Dan*_*ner 24 generics haskell deriving
使用cassava包,以下编译:
{-# LANGUAGE DeriveGeneric #-}
import Data.Csv
import GHC.Generics
data Foo = Foo { foo :: Int } deriving (Generic)
instance ToNamedRecord Foo
Run Code Online (Sandbox Code Playgroud)
但是,以下内容不是:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Csv
import GHC.Generics
data Foo = Foo { foo :: Int } deriving (Generic, ToNamedRecord)
Run Code Online (Sandbox Code Playgroud)
编译器报告:
test.hs:7:50:
No instance for (ToNamedRecord Int)
arising from the first field of ‘Foo’ (type ‘Int’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (ToNamedRecord Foo)
Run Code Online (Sandbox Code Playgroud)
这给我留下两个问题:为什么第二个版本与第一个版本不一样?为什么编译器希望找到一个实例ToNamedRecord Int呢?
Ben*_*son 15
GHC文件说:
实例上下文将根据导出时使用的相同规则生成
Eq(如果类型的类型是*),或者Functor的规则(如果类型的类型是(* -> *)).例如Run Code Online (Sandbox Code Playgroud)instance C a => C (a,b) where ... data T a b = MkT a (a,b) deriving( C )该
deriving子句将生成Run Code Online (Sandbox Code Playgroud)instance C a => C (T a b) where {}的约束
C a和C (a,b)从数据构造器参数生成的,但后者简化为C a.
所以,根据Eq规则,你的deriving条款生成......
instance ToNamedRecord Int => ToNamedRecord Foo where
Run Code Online (Sandbox Code Playgroud)
......这跟......不一样
instance ToNamedRecord Foo where
Run Code Online (Sandbox Code Playgroud)
......因为前者只有instance ToNamedRecord Int在范围内才有效(在你的情况下似乎没有).
但我觉得这个规范有些含糊不清.该示例是否真的会生成该代码,还是应该生成instance (C a, C (a, b)) => instance C (T a b)并让解算器释放第二个约束?在您的示例中,即使对于具有完全具体类型的字段,它也会生成此类约束.
我毫不犹豫地称这是一个错误,因为它是如何Eq工作的,但鉴于这DeriveAnyClass是为了使编写空实例更快,它似乎不直观.
| 归档时间: |
|
| 查看次数: |
2043 次 |
| 最近记录: |