commit ebdf81a92608364c8e81a3ac21c4e7db873a1da4 Author: Martin Potier Date: Thu Jan 11 09:24:25 2018 +0200 Initial commit diff --git a/ep0001/Solution.md b/ep0001/Solution.md new file mode 100644 index 0000000..8023d29 --- /dev/null +++ b/ep0001/Solution.md @@ -0,0 +1,163 @@ +# FPKATA #01: In the library… + +(Soundtrack: Arch Enemy — War Eternal) + +(Inspired from this exercice: http://www.codewars.com/kata/54dc6f5a224c26032800005c/train/haskell) + +## Introduction + +You are stuck in a library with a very talkative and experimental science-minded IA. It keeps repeating the following: + +> — Pleeease, can you help me? + +> — … + +> — Pleaaase, can you help? + +> — … + +> — Hellooooo? + +> — … + +Since you would really like to have peace, you dare ask: + +> — What's the matter? + +> — My code is incomplete, I've lost my code, please help! + +> — What code? What are you talking about? + +> — I really need to sort the library index and count how many books have the same first-letter reference, but only in from a list… + +> — Wait! + +> — … of characters that my master will provide. + +> This makes no sense, can't you write it down? + +A few seconds pass in total silence. Then, there's a sound coming from your right, something like an inkjet printer work at a fast pace. It's actually a printer. It throws the printed sheet of paper at you in a furious “TWEEEEEEEEEEEP”. You pick up the paper and read: + + INPUT................: + LIBRARY COUNT......: [("ABOOK", 12), ("BPDEXU", 45), ("BJLDRSA", 15), ("CLDAVB", 98), ("DAJLDI", 32)] + INDICES............: ['A','B','C','W'] + OUTPUT...............: + INDEX COUNT........: [('A',12),('B',60),('C',98),('W',0)] + TIME TO GOOD ANSWER..: 203 years + +You frown: + +> — It took you so long to find this? + +> — Can you help me? I've lost my code, my dedicated code for this task. + +> — Well, you managed to get this one right, didn't you? + +> — Nooooo! Master is going to unplug me if I use bruteforce again! Master was + very unhappy with my performance! I want to live! Please help me! + +> — Ok, all right, calmn down, there, there… What are programmed with? + +> — Elm. + +Of course it's Elm… + +## Outline + +``` +module Main exposing (..) + +import Html exposing (text) + + +type Stock + = Stock String Int + + +library1 : List Stock +library1 = + [ Stock "ABART" 20 + , Stock "CDXEF" 50 + , Stock "BKWRK" 25 + , Stock "BTSQZ" 89 + , Stock "DRTYM" 60 + ] + + +categories1 : List Char +categories1 = + [ 'A' + , 'B' + , 'C' + , 'W' + ] + + +stockList : List Stock -> List Char -> List ( Char, Int ) +stockList st cs = + + + +main = + text (toString (stockList library1 categories1)) +``` + +## Walkthrough + +Ok, so you'll have to fill the blank. After a few minutes, you identify two +main components: one is about taking the first letter of every `Stock` name. The +second is finding the amount of each `Char` in a `List (Char, Int)`. +> +Let's start with the second point and assume we have a value of `List (Char, +Int)` already available. We know at least to functions to recurse on lists: +maps and folds. Clearly, we'll have to choose a fold, since some aggregating is +needed when several identical `Char` are in the list. Let's pick foldl, it does +not really matter right now. So, the type of `List.foldl` is: + + foldl : (a -> b -> b) -> b -> List a -> b + +In fact, you notice you'll need two folds! One inner fold for counting of many +book for initial X, and one outer fold for going through all the initials +required by the master. + +### Inner foldl: how many books with Initial X + +You think about using type aliases to make your code easier to read, the IA +won't mind. To specialize your inner foldl, which is morally a foldlForX, you +identify `a` as an element of a library stock (even though the title has been +shortened already to its initial), and `b` as the final index count. + + type alias Initial = Char + type alias Count = Int + type alias TitleCount = (Initial, Int) + type alias FinalCount = (Initial, Int) + +You rewrite your specialized foldl type signature to account for the type +aliases: + + foldForX : (TitleCount -> FinalCount -> FinalCount) + -> FinalCount + -> List TitleCount + -> FinalCount + +After a call to this, you'll get how many books have a title that starts with +the initial X. + +You are missing the function with type `(TitleCount -> FinalCount -> +FinalCount)`, and you reflect a little bit on its name and on its usage. Hmmm, +it takes a TitleCount and a FinalCount and returns a (new) FinalCount? You +choose to call it: + + updateFinalCount : (TitleCount -> FinalCount -> FinalCount) + +Actually it takes another (hidden) parameter, you change its name to reflect +that: + + updateFinalCountForX : (TitleCount -> FinalCount -> FinalCount) + updateFinalCountForX t f = + + +NB: +addBio : String -> User -> User +addBio bio user = + { user | bio = bio }