简体   繁体   English

这个GHC.Generic函数签名错误消息是什么意思?

[英]What does this GHC.Generic function signature error message mean?

I'm learning Haskell. 我正在学习Haskell。 Why can't I change Person to type variable a in the method signature of getName 为什么我不能在getName的方法签名中将Person更改为类型变量a

{-# LANGUAGE DeriveGeneric #-}
module Main where

import GHC.Generics


data Person = Person { id   :: Int
                     , name :: String
                     , age  :: Int }
            deriving (Generic, Show)

p = from $ Person 12 "J" 12

getName :: (Rep Person) x -> String
-- getName :: Generic a => (Rep a) x -> String
----^ Err: Couldn't match type ‘Rep a0’ with ‘Rep a
getName f = concat [ moduleName f
                   , "_"
                   , datatypeName f
                   ]

n = getName p

Rep is an associated type-synonym ie the actual type can be anything depending on the implementation of the specific type-class instance. Rep是一个关联的类型同义词,即实际类型可以是任何东西,具体取决于特定类型类实例的实现。 There is no guarantee that Rep a for any arbitrary a is a type that is compatible with the type required by the function moduleName . 无法保证任何a Rep a是与函数moduleName所需类型兼容的类型。

Rep Person works because the compiler is able to check that the associated type for the type-class instance of Generic Person fits the type expected by moduleName (which is Datatype d => td (f :: * -> *) a ). Rep Person有效,因为编译器能够检查Generic Person的类型类实例的关联类型是否符合moduleName期望的类型(即Datatype d => td (f :: * -> *) a )。

Instead of using Rep a you can instead use 而不是使用Rep a您可以改为使用

getName :: Datatype d => t d (f :: * -> *) a -> String
getName f = concat [ moduleName f
                   , "_"
                   , datatypeName f
                   ]

Although you also need to enable the KindSignatures extension. 虽然您还需要启用KindSignatures扩展。

Just omit the type signature for getName . 只需省略getName的类型签名即可。

Running your code in a ghci session yields this: 在ghci会话中运行代码会产生以下结果:

ghci> :t getName
getName :: Datatype d => t d f a -> [Char]

ghci> getName p
"Lib9_Person"

ghci> :t getName p
getName p :: [Char]

Note: My code resides in the module Lib9 which explains the output for getName p . 注意:我的代码位于模块Lib9 ,它解释了getName p的输出。

If you want to give it a type signature, enable KindSignatures and use: 如果要为其指定类型签名,请启用KindSignatures并使用:

getName :: Datatype d => (t :: * -> (* -> *) -> * -> *) d f a -> [Char]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM