Skip to content

Instantly share code, notes, and snippets.

@throughnothing
Last active February 3, 2018 04:39
Show Gist options
  • Save throughnothing/d7cf35643964636a1b85cbd1823707c2 to your computer and use it in GitHub Desktop.
Save throughnothing/d7cf35643964636a1b85cbd1823707c2 to your computer and use it in GitHub Desktop.
Deck of things...
module CardDeck
( Card
, CardDeck
, mkCardDeck
, Suit
, Rank
) where
import Prelude (class Eq, class Ord, class Show, ($), bind, pure)
import Data.Generic.Rep.Show (genericShow)
import Data.Generic.Rep (class Generic)
import Data.List (List(..), fromFoldable)
import Data.NonEmpty ((:|))
import Partial.Unsafe (unsafePartialBecause)
import Deck (Deck, Shuffled, Unshuffled, mkDeck)
-- | Type alias for a shuffled deck of cards
type CardDeck = Deck Shuffled Card
data Suit = Clubs | Diamonds | Hearts | Spades
derive instance suitEq :: Eq Suit
derive instance suitOrd :: Ord Suit
derive instance genericSuit :: Generic Suit _
instance showSuit :: Show Suit where show = genericShow
data Rank
= Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King
derive instance rankEq :: Eq Rank
derive instance rankOrd :: Ord Rank
derive instance genericRank :: Generic Rank _
instance showRank :: Show Rank where show = genericShow
data Card = Card Suit Rank
derive instance cardEq :: Eq Card
derive instance cardOrd :: Ord Card
derive instance genericCard :: Generic Card _
instance showCard :: Show Card where show = genericShow
mkCardDeck :: Deck Unshuffled Card
mkCardDeck = unsafePartialBecause "We know we have a full deck here" deck
where
deck :: Partial => Deck Unshuffled Card
deck = let (Cons x xs) = deckList in mkDeck $ x :| xs
deckList :: List Card
deckList = fromFoldable $ do
suit <- [Clubs, Diamonds, Hearts, Spades]
rank <- [Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King]
pure $ Card suit rank
module Deck
( deckSize
, Deck
, head
, mkDeck
, Shuffled
, shuffle
, tail
, Unshuffled
) where
import Control.Monad.Gen (class MonadGen, chooseInt)
import Data.Foldable (class Foldable, foldMap, foldl, foldr)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.List (List(..), deleteAt, fromFoldable, index, length)
import Data.List (drop, take, (:))
import Data.Maybe (Maybe(..), fromJust)
import Data.Monoid (mempty)
import Data.NonEmpty (NonEmpty(..), (:|))
import Partial.Unsafe (unsafePartialBecause)
import Prelude (class Eq, class Ord, class Show, bind, mod, pure, ($), (+), (-), (<>))
-- Data type to denote a Sorted Deck
data Unshuffled
-- Data type to denote a Shuffled Deck
data Shuffled
data Deck s a = Deck (NonEmpty List a)
derive instance genericDeck :: Generic (Deck s a) _
instance showDeck :: Show a => Show (Deck s a) where show = genericShow
instance foldableDeck :: Foldable (Deck s) where
foldMap f (Deck ne) = foldMap f ne
foldl f b (Deck ne) = foldl f b ne
foldr f b (Deck ne) = foldr f b ne
deckSize :: ∀ s a. Deck s a -> Int
deckSize (Deck (NonEmpty x xs)) = (length xs) + 1
head :: ∀ s a. Deck s a -> a
head (Deck (NonEmpty x _)) = x
tail :: ∀ s a. Deck s a -> Maybe (Deck s a)
tail (Deck (NonEmpty x Nil)) = Nothing
tail (Deck (NonEmpty x (Cons y ys))) = Just (Deck $ y :| ys)
mkDeck :: ∀ a. NonEmpty List a -> Deck Unshuffled a
mkDeck ne = Deck ne
shuffle :: ∀ a m. MonadGen m => Deck Unshuffled a -> m (Deck Shuffled a)
shuffle (Deck ne) = unsafePartialBecause "It's Safe™" do
(Cons x xs) <- shuffleList $ fromFoldable ne
pure $ Deck $ x :| xs
where
shuffleList :: Partial => List a -> m (List a)
shuffleList Nil = pure mempty
shuffleList xs = do
rand <- chooseInt 0 $ (length xs) - 1
let y = fromJust $ index xs rand
ys <- shuffleList $ fromJust $ deleteAt rand xs
pure $ y:ys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment