如何为具有类型族的记录派生实例

Sau*_*nda 5 haskell type-families deriving

这是我正在尝试但无法编译的内容:

{-# 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)
Run Code Online (Sandbox Code Playgroud)

编译错误:

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)
Run Code Online (Sandbox Code Playgroud)

Ale*_*lec 6

你这里有两个问题。第一个是 GHC 告诉你的。基本上,您不能拥有依赖于类型族的实例(类型族可以存在,但前提是它获得的所有参数都是具体类型)。一旦您允许这样做,各种不好的事情就会开始发生,其中最重要的是您的类型系列的右侧可能会调用其他类型系列。

通常,可以通过将类型族应用程序移至约束来解决此类问题:

deriving instance (Show baseType, i ~ Incoming Validated baseType) => Show i
deriving instance (Show baseType, i ~ Incoming ValidationErrors baseType) => Show i
Run Code Online (Sandbox Code Playgroud)

这样做实际上使第二个问题变得明显:你的实例头太笼统了。

也就是说,我不确定是否有什么需要修复的 - 只需摆脱派生行即可。您希望第一个可以归结为:派生Show basetype给定Show basetype约束的实例(这是完全没有意义的)。第二个同样毫无意义——Either已经有一个Show.