4

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

{-# 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)

编译错误:

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)
4

2 回答 2

4

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

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

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

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

也就是说,我不确定是否有任何需要解决的问题——只要去掉派生线。您希望第一个归结为:派生一个Show basetype给定Show basetype约束的实例(这完全没有意义)。第二个同样没有意义——Either已经有一个Show.

于 2017-01-04T06:39:44.077 回答
4
于 2017-01-04T06:41:24.567 回答