Created
January 3, 2019 09:44
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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