2014-04-22 8 views
7

Mam problem z UndecidableInstances, którego nie byłem w stanie wymyślić, jak uniknąć używania newtype. Oto co miałem pierwotnie:Nierozstrzygalne substancje i nowe typy

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

Komunikat pojawia się

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

chcę uniknąć UndecidableInstances ponieważ kod ten będzie w wielokrotnego użytku biblioteki, więc próbuję deklarowania 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 

Ale pojawia się ten sam błąd. Czytałem odpowiedzi na inne pytania na temat UndecidableInstances, ale nie byłem w stanie rozwiązać tego problemu.

+0

Dlaczego dokładnie nie chcesz 'UndecidableInstances'? Nie ma w tym nic złego. – leftaroundabout

+0

Jeśli można go tutaj użyć, to jest wspaniałe. Pomyślałem tylko, że powinienem tego unikać z powodu takich postów: https://lukepalmer.wordpress.com/2008/04/08/stop-using-undecidable-instances/ – mhwombat

+1

Tu jest w porządku, o ile nie będziesz zacznij definiować instancje 'Record' oparte na jakimś' Universe'. – leftaroundabout

Odpowiedz

1

Jak okropnym kludge, podwójnego owijania i korzystania FlexibleInstances wydają rade:

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