Skip to content

Instantly share code, notes, and snippets.

@DonaldKellett
Created January 3, 2019 09:44
Show Gist options
  • Save DonaldKellett/c785707372ed74ee1646eb9630d42295 to your computer and use it in GitHub Desktop.
Save DonaldKellett/c785707372ed74ee1646eb9630d42295 to your computer and use it in GitHub Desktop.
PureScript by Example - 6.12 A Type Class for Hashes - Exercise 2-3 Solutions
module Hashable
( HashCode
, hashCode
, class Hashable
, hash
, hashEqual
, combineHashes
) where
-- Supplementary module for MoreHashables.purs
-- Adapted from https://github.com/paf31/purescript-book/blob/master/exercises/chapter6/src/Data/Hashable.purs
-- with minor modifications for compatibility with PureScript v0.12.0
-- (the original version linked above is compatible with PureScript v0.11.x)
import Prelude
import Data.Char (toCharCode)
import Data.Either (Either(..))
import Data.Foldable (foldl)
import Data.Function (on)
import Data.Maybe (Maybe(..))
import Data.String.CodeUnits (toCharArray)
import Data.Tuple (Tuple(..))
newtype HashCode = HashCode Int
hashCode :: Int -> HashCode
hashCode h = HashCode (h `mod` 65535)
class Eq a <= Hashable a where
hash :: a -> HashCode
instance showHashCode :: Show HashCode where
show (HashCode h) = "(HashCode " <> show h <> ")"
derive instance eqHashCode :: Eq HashCode
combineHashes :: HashCode -> HashCode -> HashCode
combineHashes (HashCode h1) (HashCode h2) = hashCode (73 * h1 + 51 * h2)
hashEqual :: forall a. Hashable a => a -> a -> Boolean
hashEqual = eq `on` hash
instance hashChar :: Hashable Char where
hash = hash <<< toCharCode
instance hashString :: Hashable String where
hash = hash <<< toCharArray
instance hashInt :: Hashable Int where
hash = hashCode
instance hashBoolean :: Hashable Boolean where
hash false = hashCode 0
hash true = hashCode 1
instance hashArray :: Hashable a => Hashable (Array a) where
hash = foldl combineHashes (hashCode 0) <<< map hash
instance hashMaybe :: Hashable a => Hashable (Maybe a) where
hash Nothing = hashCode 0
hash (Just a) = hashCode 1 `combineHashes` hash a
instance hashTuple :: (Hashable a, Hashable b) => Hashable (Tuple a b) where
hash (Tuple a b) = hash a `combineHashes` hash b
instance hashEither :: (Hashable a, Hashable b) => Hashable (Either a b) where
hash (Left a) = hashCode 0 `combineHashes` hash a
hash (Right b) = hashCode 1 `combineHashes` hash b
module MoreHashables where
-- Main solution for the exercises in PureScript by Example
-- 6.12 A Type Class for Hashes
-- N.B. This solution file relies extensively on a non-standard module
-- Hashable defined in Hashable.purs which is also included in this gist
import Prelude
import Hashable
import Data.Array
import Data.Function
-- Exercise 2
hasDuplicates :: forall a. Hashable a => Array a -> Boolean
hasDuplicates arr = nubByEq (eq `on` hash) arr /= arr
-- Boilerplate for Exercise 3
newtype Hour = Hour Int
instance eqHour :: Eq Hour where
eq (Hour n) (Hour m) = mod n 12 == mod m 12
-- Exercise 3
instance hashHour :: Hashable Hour where
hash (Hour n) = hash (mod n 12)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment