错误RECURSIVE数据类型使用YESOD

时间:2016-02-12 17:04:44

标签: haskell recursion types yesod persistent

TL; DR如何制作(密钥记录)Yesod中的Eq / Show / Read实例

我遇到模块递归问题。我已经在一个文件中声明了我自己的一些数据类型,我希望它可以用于Models.hs,因为我需要在config / models文件中使用它。 但其中一种类型需要来自数据库的数据类型。确切地说是FooId(即Key Foo)。

它看起来像这样:

配置/模型

Foo
    name Text
    thingy (Bar Foo) Maybe
    UniqueName name
    deriving Eq Show Read Typeable

我自己的文件包含这些

data Bar record = Bar { a :: [Jab record] }
  deriving (Eq, Show, Read, Typeable)

data Jab record = Jab { b :: Key record
                      , c :: Int
                      }
  deriving (Eq, Show, Read, Typeable)

现在我需要导入Model.hs以使Key工作,但我还需要将我的文件导入Model.hs才能工作。 我也尝试将自己的类型添加到Models.hs,但是我收到了这些错误:

Model.hs:24:13:
    No instance for (Eq (Key record))
      arising from the first field of ‘Jab’ (type ‘Key record’)
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Eq (Jab record))

添加"派生实例Eq a => Eq(键a)" 与{ - #LANGUAGE StandaloneDeriving# - }一起使用也不起作用。

如果有人知道如何解决这个问题,它会帮助我。

1 个答案:

答案 0 :(得分:1)

Turns out writing my own instances for (Jab record) fixed this issue.

This is how I fixed it, for reference:

  • Removing the Eq, Show and Read from the deriving clause of Jab
  • Making my own Eq, Show and Read instances for (Jab record)
  • After that compiled I had to consequently make a PersistField instance for (Bar record)

(The following is all put in a separate file to be imported to Models.hs)

module Custom.TypesAndInstances where

import ClassyPrelude.Yesod

import Prelude (read)
import qualified Data.Text as T
import qualified Text.Read.Lex as L
import Text.ParserCombinators.ReadPrec
import GHC.Read
import GHC.Show (appPrec)

-- instance for PersistField (Bar record)

instance (PersistEntity record, PersistField record) => PersistField (Bar record) where
    toPersistValue = PersistText . T.pack . show
    fromPersistValue (PersistText t) = Right $ read $ T.unpack t

-- instances for Jab Eq, Read and Show

instance PersistEntity record => Eq (Jab record) where
    Jab x a == Jab y b = x == y && a == b  

instance PersistEntity record => Show (Jab record) where
    show (Jab x a) = "Jab " ++ show x ++ " " ++ show a

instance PersistEntity record => Read (Jab record) where
    readPrec = parens
        (prec appPrec (do
            expectP (L.Ident "Jab")
            x <- step readPrec
            y <- step readPrec
            return (Jab x y))
        )
    readListPrec = readListPrecDefault
    readList = readListDefault

----------------------
data Bar record = Bar { a :: [Jab record]
                                    }
  deriving (Eq, Show, Read, Typeable)

data Jab record = Jab { b :: Key record  
                      , c :: Int
                      }
  deriving (Typeable)