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

Ale*_*lin 6 haskell yesod

我正在尝试Data.HashMap通过按外键字段对多个Persistent实体进行分组来构建结构.比如说我有这两个实体(直接来自Yesod书)

Person
    name String
    age Int Maybe
    deriving Show
BlogPost
    title String
    authorId PersonId
    deriving Show
Run Code Online (Sandbox Code Playgroud)

我想要一个:

HashMap PersonId [BlogPost]
Run Code Online (Sandbox Code Playgroud)

这里的挑战是PersonId没有直接实现Hashable(来自Data.Hashable),另外它根据你正在使用的数据库进行抽象(在我的情况下是Postgres).

我想(只是一个疯狂的初学者猜测)我可以通过执行fromPersistValueread进入Int64 实现Hashable for PersonId ,其中已经有一个Hashable实现,但我想可能有一种不太复杂的方法来实现它.

有什么建议?

Rom*_*aka 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)
Run Code Online (Sandbox Code Playgroud)


bit*_*app 4

它必须是一个吗HashMapData.Map只需要Ord。该类Hashable有点狡猾,无论如何都可以使用修复程序。

除非您知道自己在做什么并了解散列行为中的缺陷,Hashable否则永远不应该使用HashMapaData.Map会做的事情。

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