不可判断的实体和新类型

时间:2014-04-22 10:14:47

标签: haskell

我遇到UndecidableInstances问题但我无法弄清楚如何避免使用newtype。这是我原来的:

{-# LANGUAGE TypeFamilies, FlexibleContexts #-}

class Record r where
  key :: r -> String

class (Record r) => SizedRecord r where
  size :: r -> Int

class Database d where
  type DBRecord d

class (Record a) => Agent a where
  agentId :: a -> String
  agentId = key

class (Database (UAgentDB u), Agent (UAgent u), Record (UAgent u))
      => Universe u where
  type UAgent u
  type UAgentDB u
  -- plus other stuff

data SimpleUniverse d = SimpleUniverse
  {
    suDB :: d
    -- plus other stuff
  } deriving (Show, Eq)

instance (Record (DBRecord d)) => Universe (SimpleUniverse d) where -- line 28
  type UAgent (SimpleUniverse d) = DBRecord d
  type UAgentDB (SimpleUniverse d) = d
  -- plus other stuff

我得到的信息是

amy9.hs:28:10:
    Constraint is no smaller than the instance head
      in the constraint: Record (DBRecord d)
    (Use -XUndecidableInstances to permit this)
    In the instance declaration for `Universe (SimpleUniverse d)'

我想避免使用UndecidableInstances,因为此代码将位于可重用的库中,因此我尝试声明newtype

newtype SimpleUniverse2 u = SimpleUniverse2 { fromAdditiveGroup :: u }

instance (Record (DBRecord u)) => Universe (SimpleUniverse2 u) where
  type UAgent (SimpleUniverse2 u) = DBRecord u
  type UAgentDB (SimpleUniverse2 u) = u
  -- plus other stuff

但我得到同样的错误。我已经在UndecidableInstances上阅读了其他问题的答案,但我还没有能够解决这个问题。

1 个答案:

答案 0 :(得分:1)

作为一个可怕的kludge,双重包装并使用FlexibleInstances似乎可以解决问题:

import Control.Monad.Identity    

instance (Database u, Agent (DBRecord u), Record (DBRecord u)) =>
         Universe (Identity (Identity u)) where
  type UAgent (Identity (Identity u)) = DBRecord u
  type UAgentDB (Identity (Identity u)) = u