Skip to content

Instantly share code, notes, and snippets.

@StevenXL
Created December 21, 2018 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StevenXL/23a3b61e447f27d4bd345270697cc212 to your computer and use it in GitHub Desktop.
Save StevenXL/23a3b61e447f27d4bd345270697cc212 to your computer and use it in GitHub Desktop.
Example usage of Scope Type Variables
{-# LANGUAGE ScopedTypeVariables #-}
module Cipher where
data FourLetterAlphabet = L1 | L2 | L3 | L4 deriving (Show, Enum, Bounded)
-- Because of ScopedTypeVariables, the type variable "a" in the where clause
-- refers to the same type variable "a" as in the function's signature.
--
-- When we apply rotN to a value, all instances of "a" will be instantiated to
-- the type of that value. If we had not used ScopedTypeVariables, then the "a"
-- type variable in the where clause would not be instantiated, and we could not
-- resolve minBound and maxBound.
rotN :: forall a. (Bounded a, Enum a) => a -> a
rotN char = toEnum rotated
where rotated = offset `mod` alphabetSize
offset = fromEnum char + halfAlphabetSize
halfAlphabetSize = alphabetSize `div` 2
alphabetSize = mL [minBound .. maxBound]
mL :: [a] -> Int
mL = length
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment