通过Persistent的实体密钥进行哈希?

时间:2014-06-01 02:34:15

标签: haskell yesod

我试图通过按外键字段对多个Persistent实体进行分组来构建Data.HashMap结构。例如。说我有这两个实体(straight out of the Yesod book

Person
    name String
    age Int Maybe
    deriving Show
BlogPost
    title String
    authorId PersonId
    deriving Show

我想要一个:

HashMap PersonId [BlogPost]

这里的挑战是PersonId没有直接实现Hashable(来自Data.Hashable),而且它根据您使用的数据库进行抽象(在我的情况下是Postgres)。< / p>

我想(只是一个疯狂的初学者猜测)我可以通过将fromPersistValueread添加到Int64中来实现Hashable for PersonId,其中已经有Hashable实现,但是我想象一下,实现这一目标可能会有一种不那么复杂的方式。

有什么建议吗?

3 个答案:

答案 0 :(得分:6)

您可以以少数孤儿实例的价格执行此操作。您可以在下面找到完整的代码。

PersonId只是KeyBackend SqlBackend Person的别名,因此instance Hashable (KeyBackend b e)就是您所需要的。对于可能最终成为Hashable部分内容的其他类型,其余声明派生PersonId

{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveGeneric #-}

module HashableInstances where

import Database.Persist
import GHC.Generics
import Data.Hashable
import Data.Time
import Data.Fixed

instance HasResolution e => Hashable (Fixed e) where
  hashWithSalt s = (hashWithSalt s :: Double -> Int) . realToFrac
deriving instance Generic Day
instance Hashable Day
deriving instance Generic LocalTime
instance Hashable LocalTime
deriving instance Generic TimeOfDay
instance Hashable TimeOfDay
deriving instance Generic TimeZone
instance Hashable TimeZone
instance Hashable DiffTime where
  hashWithSalt s = (hashWithSalt s :: Double -> Int) . realToFrac
deriving instance Generic UTCTime
instance Hashable UTCTime
deriving instance Generic ZonedTime
instance Hashable ZonedTime
deriving instance Generic ZT
instance Hashable ZT
deriving instance Generic PersistValue
instance Hashable PersistValue
deriving instance Generic (KeyBackend b e)
instance Hashable (KeyBackend b e)

答案 1 :(得分:3)

是否必须是HashMapData.Map只需要OrdHashable类有点狡猾,无论如何都可以使用修复。

除非您知道自己正在做什么并了解Hashable散列行为中的缺陷,否则永远不要使用HashMapData.Map

这具有避免不必要的孤立实例的副作用。 (Ord比Hashable更多的东西)

答案 2 :(得分:0)

更新Roman的最新(2.x)版本的Persistent:

{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveGeneric #-}

module HashableInstances where

import Database.Persist
import GHC.Generics
import Data.Hashable
import Data.Time

deriving instance Generic Day
instance Hashable Day
deriving instance Generic LocalTime
instance Hashable LocalTime
deriving instance Generic TimeOfDay
instance Hashable TimeOfDay
deriving instance Generic TimeZone
instance Hashable TimeZone
instance Hashable DiffTime where
  hashWithSalt s = (hashWithSalt s :: Double -> Int) . realToFrac
deriving instance Generic UTCTime
instance Hashable UTCTime
deriving instance Generic ZonedTime
instance Hashable ZonedTime
deriving instance Generic PersistValue
instance Hashable PersistValue

instance (PersistEntity a) => Hashable (Key a) where
  hashWithSalt s k = hashWithSalt s $ keyToValues k