如何派生具有类型族记录的实例 [英] How to derive instances for records with type-families

查看:137
本文介绍了如何派生具有类型族记录的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b

  { - #LANGUAGE TypeFamilies# - } $ b这是我正在尝试的但不能编译的内容$ b $  -  $ L $ 
导入Data.Text作为T
导入Data.Int(Int64)$ b $ $ b $ - {$#$}
{ - #LANGUAGE FlexibleInstances# b
类型系列传入validationResult baseType
类型实例传入验证baseType = baseType
类型实例传入ValidationErrors baseType =任一[T.Text] baseType

数据已验证
data ValidationErrors

data Tag = Tag {unTag :: T.Text}派生(Eq,Show)

数据NewTag f = NewTag
{
ntClientId :: Incoming f Int64
,ntTag :: Incoming f Tag
}

派生实例(Show baseType)=> Show(Incoming Validated baseType)
派生实例(Show baseType)=> Show(Incoming ValidationErrors baseType)

编译错误:

  23 38错误错误:
•实例中的非法类型同义词族应用程序:
传入验证的baseType
•在独立派生实例
'(Show baseType)=> Show(Incoming Validated baseType)'(intero)
24 38错误错误:
•实例中非法类型同义词族应用程序:
Incoming ValidationErrors baseType
•在独立派生
'(Show baseType)=>的实例Show(Incoming ValidationErrors baseType)'(intero)


解决方案

您这里有两个问题。第一个是GHC告诉你的。基本上,你不能有一个依赖于类型族的实例(类型族可以在那里,但只有当它获得的所有参数都是具体类型时)。一旦你允许,各种不好的事情都可能开始发生,其中最重要的是你类型家庭的右手边可以打电话给其他家庭。



通常,可以通过将类型系列应用程序移动到一个约束来解决这类问题:

 派生实例(Show baseType, i〜传入验证的baseType)=>显示i 
派生实例(Show baseType,i〜Incoming ValidationErrors baseType)=>显示我

这样做实际上使得第二个问题显而易见:您的实例头太笼统了。



也就是说,我不确定还有什么需要解决的 - 就是摆脱派生线。您希望第一个归结为说:在给定显示基类型约束条件下派生一个显示基类型的实例这是完全没有意义的)。第二个同样没有意义 - 或者已经有一个 Show 的实例。


Here's what I'm trying but it doesn't compile:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleInstances #-}

import Data.Text as T
import Data.Int (Int64)

type family Incoming validationResult baseType
type instance Incoming Validated baseType = baseType
type instance Incoming ValidationErrors baseType = Either [T.Text] baseType

data Validated
data ValidationErrors

data Tag = Tag {unTag :: T.Text} deriving (Eq, Show)

data NewTag f = NewTag
  {
    ntClientId :: Incoming f Int64
  , ntTag :: Incoming f Tag
  }

deriving instance (Show baseType) => Show (Incoming Validated baseType)
deriving instance (Show baseType) => Show (Incoming ValidationErrors baseType)

Compilation errors:

23  38 error           error:
 • Illegal type synonym family application in instance:
     Incoming Validated baseType
 • In the stand-alone deriving instance for
     ‘(Show baseType) => Show (Incoming Validated baseType)’ (intero)
24  38 error           error:
 • Illegal type synonym family application in instance:
     Incoming ValidationErrors baseType
 • In the stand-alone deriving instance for
     ‘(Show baseType) => Show (Incoming ValidationErrors baseType)’ (intero)

解决方案

You have two problems here. The first one is what GHC is telling you. Basically, you can't have an instance that depends on a type family (the type family can be there, but only if all the arguments it gets are concrete types). All sorts of bad things can start happening once you allow this, not the least of which is that the right hand side of your type family could have calls to other type families.

Generally, one can solve this sort of problem by moving the type family application to a constraint:

deriving instance (Show baseType, i ~ Incoming Validated baseType) => Show i
deriving instance (Show baseType, i ~ Incoming ValidationErrors baseType) => Show i

Doing this actually makes the second problem obvious: your instance heads are too general.

That said, I'm not sure there is even anything to fix - just get rid of the deriving lines. You would like the first one to boil down to saying: derive an instance of Show basetype given the Show basetype constraint (which is completely pointless). The second one is equally pointless - Either already has an instance of Show.

这篇关于如何派生具有类型族记录的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆