1. 14
    Pull Many Random Numbers in a Single State ADT Transaction
    4m 58s

Pull Many Random Numbers in a Single State ADT Transaction

Share this video with your friends

Social Share Links

Send Tweet
Published 5 years ago
Updated 3 years ago

We have the ability to select a single random card from a pile of twelve cards, but we would like to pull a total of nine. Not only that, we would like to match the same transition functions we have been writing all along.

Lucky for use there are three types of functions, or morphisms that we can use to get us everything we need. We use an anamorphism to expand our one function into a list of nine functions. Each of these functions are endomorphisms, so we can use the mreduce catamorphism with the Endo Monoid to fold them down into one function that we can use to get this action into our state transactions.

Instructor: [00:00] We begin with this getDeck function that returns a state instance with a pair in the resulting, containing a pile of cards generated by the 12 permutations of these 2 arrays in state. Using FST, we'll peek in on the left side of the pair to find an empty array just itching to be populated with one of the 12 cards in the array that we have on the right.

[00:20] We also have this drawRandom function that takes a deck as its input and returns a state instance that uses this seed to move a random card from the right pile to the left. When we chain it in, we see our right pile has been decreased by one.

[00:34] To see where it's gone to, we check the left side to find it now contains this yellow square. We would like to do this nine times in total. Over in our game model we create a new state transaction, called drawNine, that we define a little differently than our other transactions.

[00:49] It's defined as an endomorphism that takes the stateApp state of deck, and then brings it right back into the same stateApp state of deck. We'll reach for this repeat helper that takes an integer in any type A to an array of As. Repeat is an endomorphism that gives us back an array populated with num, numberOfElms.

[01:09] Which means we can give it nine as it's first argument, and then satisfy the second argument with the point-free chain on drawRandom to get back an array of functions that match our signature. To get an inkling of what we're working with here, we'll jump back into our index and replace our outdated drawRandom with this soon-to-be supercharged drawNine.

[01:29] Seeing we get back an array of nine functions, but not just any functions. They're all endomorphisms for the type stateApp state of deck.

[01:37] Which means we can fold them, using mReduce with the endomonoid, which unwrapped the resulting endomorphism, ready for use, proving what my grandpappy used to always say, "Endomorphisms pair nicely with catamorphisms."

[01:50] DrawNine is now ours for the calling. We pass it the state instance we get back from calling getDeck, and then check out the resultant by calling evalWith with our initial state. Seeing our expected pair full of cards on the left, and a quick check on the length, shows our expected total of nine.

[02:07] Nine random cards, while the right still houses the remaining three. Seems legit, indeed, but now we're faced with the challenge of using this function in a way cornsistent with the rest of our transitions. Why not capture this in a new composition, called drawFromDeck? While you may not see it at first, we've already created this composition.

[02:27] We just need to move this bit into our function and use the cross-compose helper to get it into a more familiar style by arranging it into compose, so that it returns the result of drawNine being called with the results of getDeck. We now have a function that acts like all of our other state transactions.

[02:45] We can define drawFromDeck as a function that goes from unit to a stateApp state of deck. To see our finished transition in action, we just meander on up to the top and get rid of all this noise, replacing it with drawFromDeck.

[02:59] Due to referential transparency, with the old swapping call, we see the same length of nine in the pairs first, corresponding to our nine drawn cards. Over in the second, we see the remaining cards, with our expected length of three.

[03:14] We should probably do something with these cards, so why not just add them to our state on this cards attribute? Popping back over to our game model, we create a transaction that we aptly name, setCards, taking a deck as it's input. We define this new setCards state transition as a function that takes a deck to our all-too-familiar stateApp state of unit.

[03:37] We implement said cards with our over helper pointed at the cards attribute, and load up the crocs-constant combinator with the draw pile from the first portion of our deck. setCards takes a deck as its input, while our drawFromDeck function returns a state instance with deck in its resultant.

[03:54] Which means we can combine them by chaining. Let's export a brand new state transition that we'll name with a plural pickCards. We'll define this new pickCards transaction as a function that takes the unit from drawFromDeck to the stateApp state of unit returned from setCards.

[04:12] Because we have two Kleislis, we'll use composeK to define a composition of setCards after drawFromDeck, thus allowing us to randomly pick nine cards, and place them in the cards portion of our state, with one function call.

[04:25] Which we can now show off in our index by pulling it in and replacing drawFromDeck in the down below. Then we swap out a vowel width with exitWith to take a look at our newly transitioned state.

[04:37] Focusing in on the cards attribute, we find it to be populated with our expected cards, with a length of nine. We seem to be getting the same random 9 every time, due to the constant value of 23 for our seed. By changing it to date.now we see a fresh new deck with every single save. So good.

egghead
egghead
~ 27 minutes ago

Member comments are a way for members to communicate, interact, and ask questions about a lesson.

The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io

Be on-Topic

Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.

Avoid meta-discussion

  • This was great!
  • This was horrible!
  • I didn't like this because it didn't match my skill level.
  • +1 It will likely be deleted as spam.

Code Problems?

Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context

Details and Context

Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!

Markdown supported.
Become a member to join the discussionEnroll Today