Если вы видите что-то необычное, просто сообщите мне. Skip to main content

Часть 3: Haskell и взвешенная практика

Вы были в ситуации когда вы пытаетесь изучить что-то в определенное время, и застряли на этом? Шанс, что вы изучаете предмет не лучшим способом. Но как вы можете узнать, что входит в это "хорошее" изучние вашей темы? Оно может разочаровать при попытке найти что-то в интернете. Большинство людей не думают о том способе которым они изучают новое. Они изучают, но они не могут выразить и обучить других людей тому, что они делают, потому что для этого нет инструкции.

Часть 1 этой главы говорит нам о том, почему вы не должны бояться пробовать изучить Haskell. Часть 2 обсуждает некоторые техники на высшем уровне. Эта часть пройдется по паре ключевых идей из "Art of Learning" Джоша Вайтцкина. Мы рассмотрим на то, как избежать проблему застрявания.

Первая идея, о которой мы загооврим это идея взвешенной практики. Цель этой практики прицелиться в конкретную идею и попробовать улушчить определенные навыки до тех пор, пока они будут только в подсознании. Вторая идея - роль ошибок в изчении любого нового навыка. Мы будем использовать это для стимула ведущего дальше, которы предостережот нас от этой же идеи в будущем.

Мы раскроем это в 4 части, в которой разберем применение этой техники в изучении Haskell.

Некоторые техники проще понять, если вы уже имеете какую-то практику в изучении Haskell.

Взвешенная практика

Предположим, на минуточку, вы учите композицию на фортепьяно. Наибольшее искушение здесь это "учите" часть повторяя композицию от начала до конца. Часть у вас получлается, часть - нет. В итоге, вы изучили большую часть. Это заманчивый способ практки по нескольким причинам:

  1. Это "очевидный" выбор.
  2. Он позволяет нам проиграть часть, которую мы уже узнали и получить удовольствие от этого.
  3. Скорей всего в результате мы выучим композицию.

Однако, это не оптимальный метод со стороны обучения. Если вы хотите улучшить вашу возможность играть вашу композицю от начала до конца, вы должны сфокусироваться на слабых местах. Вам нужно найти определенные пассажи, которые вам даются хуже всего. Как только вы их определите, вы можете разбирать их дальше. Вы можете найти определенную размерность или даже ноты с которыми у вас проблемы. Вы должны практиковать слабые места снова и снова, исправляя одну маленькую вещь за другой. Отсюда, вам нужно пройти весь путь и это заставляет вас ожидать, что вы будете уверенны что вы изучили все свои "слабыу" места.

Фокусируясь на маленьких вещях - главная часть. Вы не можете взять хитрый пассаж о котором ничего не знаете и сыграть его правильно от начала до конца. Вы можете начать с одной части, которая заставляет вас ускорится. Вы можете тренироваться много раз просто фокусируясь на получении последней ноты и двигаться руку дальше. Вас не волнует ничего кроме реппетиции. Как только движение вашей руки переходит в подкорку, вы можете идти дальше к следующей части. Следующий шаг уже нужен, чтобы убедиться что вы достигли первых трех нот.

Это идея взвешенной практики. Мы фокусируемся на одной вещи во времени, и практикуем её неспеша. Бездумная практика, или практика рази практики будет давать вам маленький прогресс. Даже может уменьшить прогресс если мы заимеем плохие привычки. Мы можем применять это к любому навыкы, включая программирование. Мы хотим нахватать маленькие привычки, которые будут постепенно делать нас лучше.

Ошибки

Взвешенная практика это система построения навыков, которую мы хотим. Однако, есть множество привычек, которые мы не хотим. Мы делаем много вещей, ошибки которых мы поймем позже. И наихудшая вещь это когда мы понимаем, что мы повторяем одну и ту же ошибку.

Вайцкин отмети в "Art of Learning": Если студент любого предмета может избежать хотябы повтора одной и той же ошибки дважды, они быстро достигнут высот в изучаемой теме. Мы так же можем сделать это если будем избегать ошибок в целом, но это не возможно. Мы всегда делаем ошибки, пробуя что-то впервые.

SoСначала firstнужно weпринять, haveчто toошибки embraceбудут theслучаться. certaintyКак thatтолько mistakesмы willэто happen.сделаелм, Onceу we’veнас doneбудет this,решение weкак canэтого haveизбежать. aНевозможно planизбежать forповторения dealingошибок, withно them.мы Weможем won’tпредпринять beшаги, ableкоторые toсократят avoidих everколичество. repeatingИ mistakes,если butмы weтакое canможем takeсделать, stepsто thatувидим willсущественное reduceулучшение. theНаше rateрешение atбудет whichхранить weвсе do.ошибки Andкоторые ifмы we’reсделаем. ableОписывая toвсё, doчто this,происходит, we’llмы seeрезко majorсократим improvement.повторение Our solution will ultimately be to keep a record of the mistakes we make. By writing things, down, we'll dramatically reduce the repetition of errors.ошибок.

PRACTICINGПрактикуем HASKELL

SoТеперь nowнам weнужно needсделать toшаг stepназад backв intoмир theнаписания landкода ofи codingспросить andсебя, askкак ourselvesмы howможем weприменить canэти applyидеи these ideas toк Haskell. WhatНа specificкаких areasтемах ofпрактики ourнаписания codingкода practicesмы canможем we focus on?остановиться?

YouВы couldможете writeнаписать anприложение, application,и andсфокусироваться focusна onприобретении nothingследующей butпривычки: buildingпрежде theчем followingвы habit:напишете beforeфункцию, youнужно writeвынести aнеопределенности function,и stubубедиться, itчто outтипы asсигнатур undefinedкомплируются(мы andэто makeобсудим sureдальше theв typeчасти signature4). compilesНе (we'llважно discussесли thisвы techniqueвсё inостальное moreсделали detailправильно! inПриобретя partэту 4!привычку Itможноприступать doesn'tк matterследующему ifшагу. youВы doможете anythingубедиться elseв right!том, Afterчто you'veвы gottenвсегда intoпишете thatвызов habit,функции youпрежде couldчем alsoвы takeеё another step. You could make sure you always write the function’s invocation (where your other code calls the function) before you implement it.реализуете.

I’veЯ chosenвыбрал theseэти examplesпримеры, becauseпотому thereчто areесть twoдве thingsвещи thatкоторые slowтормозят usнас theбольше mostвсего whenпри writingнаписании functions.функции. TheПервое first- isэто aнехватка lackясности, ofпотому clarityчто becauseмы weне don’tзнаем knowточно exactlyкак howнаш ourкод codeбудет willиспользовать useфункцию. theВторое function.- Theповторение secondработы isкогда theмы repetitionпоняли. ofчто workнам whenнужно weпереписать realizeфункцию. weЭто needслучается, toкогда re-writeмы theне function.учитываем Thisдополнительные canвозможности. happenЭти becauseпривычки, thereпродуманны wasтаким anобразом, extraчтобы typeваша weжизни didn’tстановилась accountлегче, forкогда orнужно somethingреализовать like that. These habits are designed to get you to plan more up front so that your life is simpler when it comes to implementation.их.

HereЕсть areеще aнесколько coupleпохожих of other ideas in a similar vein:идей:

  1. BeforeПрежде writingчем aписать function,функцию, writeнапишите aкоммент commentописывающий describingэту that function.функцию.
  2. BeforeПрежде youчем useиспользовать expressionsвыражение fromиз aбиблиотеки, library,добавьте addеё itв toваш your .cabal file.файл. Then,Затем, writeнапишите theвыражение import statementчтобы toубедиться, makeчто sureвы youиспользуете areправильную using the right dependency. Another great practice is to know how you will test a piece of functionality before you implement it. Ideally, you would write unit test cases for that function. But if it’s a very simple feature, like getting a line of input and parsing it in some way, you can get away with simpler ideas. You could commit to running your program on the command line with a couple types of input, for instance. As long as you know your approach before you start coding, it counts. It might be most helpful to write the test plan in some document first.зависимость.

SoЕще inодин almostспособ all- theзнать aboveкак cases,проверить theкусок “trigger”функциональности forпрежде buildingчем thisреализовать habitеё. isВ writingидеале, aнаписать newюнит function.тесты Theдля triggerфункции. isНо theесли mostэто importantчто-то partпростое, ofкак buildingполучение aстроки newввода habit.и Itеё isобработка theкаким-то actionспособом, thatвы tipsможете yourопустить brainпростые offидеи. thatВы youможете shouldвложить beв doingрабочую somethingпрограмму, you’reдля notкомандной accustomedстроки, toдва doing.вида Inвходных thisданных. case,Если theвы triggerзнаете couldсвой beподход writingдо theтого, ::как forначнете theпрограммировать, typeэто signature.имеет Everyзначение. timeИмеет youсмысл doнаписать this,план remindтестирования yourselfв ofкаком-то yourдокументе currentдля goal.начала.

Here’sВ anбольшинстве ideaслучаев withтриггером aдля differentприобретения trigger.этой Everyпривычки timeэто youнаписание pickновой aфункции. structureТриггер toэто containважная yourчасть dataприобретения новой ошибки. Это действие которое подсказывает вашему мозгу, что вы должны делать что-то не привычное. В этом случае, триггером будет написание :: для сигнатуры. Каждый раз, выполняя это, вспоминайте о вашей цели.

Есть еще идея с множеством триггеров. Каждый раз вы выбираете структуру для хранения ваших данных(list,списко, sequence,последовательность, set,набор, map,карты etc.и т.д.), brainstormкак atминимум leastтри threeразных alternatives.типа. OnceКак youтолько getвыходите beyondза theпредели basics,базовых you’llвещей, findвы eachнайдете structureуникальную hasсилу itsв uniqueкаждой strengths.из Itструктур. wouldБудет beползено mostесли helpfulвы ifвыпишите youусловия wroteсделанного downвыбора. yourТриггер, reasoningв forэтом yourслучае, finalбудет choice.проявляться Theкаждый triggerраз, inкогда thisвы caseпишете couldключевые beданные. everyДля timeболее youсложной writeверсии, theтриггером dataможет keyword.быть Forбыть aнаписание moreлевой extremeскобки version,для theначала triggerсписка. couldКаждый beраз, writingделая downэто, theспросите leftсебя: bracketможете toли startвы aиспользовать list.другую Each time you do this, ask yourself if you could be using a different structure.структуру?

Here'sИ oneпоследняя finalвозможность. possibility.Каждый Everyраз timeделая youсинонимы makeтипов, aспросите: typeстоит synonym,ли askсоздавать yourselfновый ifтип? youЭто wouldчасто beведет betterк servedулучшеню makingвремени aкомпиляции. newtypeВы outскорей ofвсего itвидели instead.сообщения Thisоб oftenошибках leadsи toбольшую betterчасть compileполучите timeеще behaviors.при You'llсборке. likelyТриггер seeтут clearerтоже errorпростой: messages,каждый andраз you'llкогда catchпишете moreключевое ofслово your errors at compile time. The trigger here is also simple: any time you type the keyword type.типа.

Here’sЭто theваждые mostвещи. importantНе thingпытайтесь though.выучить Don’tсразу tryвсе! moreВам thanнужно oneвыбрать ofодну, theseпрактиковать atеё aпока time!она Youбудет wantработать toподсознательно, pickи oneзатем thing,двигайтесь practiceк itдругой. untilЭто itсамая becomesсложная subconscious,часть andвзвешенной thenпрактики: moveуправлять onсвоим toтерпением. otherСамое things.большое Thisвлечение isэто theдвигаться hardestи partпробовать aboutновые deliberateвещи, practice:прежде maintainingчем yourусвоится patience.привычка. TheКак biggestтолько temptationвы isпереключитесь toна moveдругие onвещи, andвы tryможете newпотерять, thingsто oftenнад beforeчем theработали. goodПомните, habitsобучение areсложный solidified.процесс! OnceВам youнужно shiftсделать yourнебольшое focusисследование ontoкоторое otherтребует items,определенное youвремя. mightВы loseне whateverсможете itускорить wasэтот you were working on! Remember to treat learning like compound interest! You need to make small investments that stack up over a long period time. You can't hurry the process.процесс.

TRACKINGОтслеживание MISTAKESошибок

Let'sДавайте alsoпредставим considerразличные theспособы, variousкоторые waysпомогут weнам canизбежать avoidповторения makingошибок theв sameбудущем. mistakesОпять, inэти theразличные future.навыки Again,вы theseприобретаете areс differentпомощью fromвзвешенной theпрактики. “skills”Они youне buildпоявляются upчасто, withи deliberateвам practice.не Theyнужно don'tих occur"практиковать". much,Вам andнужно youпросто don’tпомнить, wantкак toисправить “practice”некоторые them.ошибки, Youчтобы justв wantтот toмомент rememberкогда howони youпоявятся fixedвы someсможете issueэто soприменить youеще canраз. solveВы itможете againвести ifсписок itужасных doesошибок comeв up.электронном Youвиде, shouldкоторые keepвстречаете aво listвремя in a google doc of all the worst mistakes you’ve encountered in your programming. The google doc should record three things for each mistake.программирования.

  1. WhatКак wasсебя theповел compiler message or runtime behavior?сборщик?
  2. WhatВ wasчем theзаключалась problemпроблема withс your code?кодом?
  3. HowКак didэто youможно fixисправить?
  4. it?

So for an example, think about a time you were certain your code was correct. You look at the error, then back to your code, then back to the error. And you're still sure your code is right. Of course, the compiler is (almost) always right. You want to document these so they don't trip you up again.

Other good candidates are those runtime errors where you cannot for the life of you track down where the error even occurred in your code. You’ll want to write down what this experience was like so the next time it happens, you’ll be able to fix it quickly. By writing about it, you’ll also motivate yourself to avoid it as well.

Then there are also dumb mistakes that you should record because it’ll teach you the right way faster. Like when you’re starting out you might use the (+) operator to try to append two strings instead of the (++) operator. By writing down errors like this, you'll learn quirky language features much faster.

One final group of things you should track down is awesome solutions. Not just bug fixes, but solutions to your central programming problems. For instance, you found your program was too slow, but you used a better data structure to improve it. Not only does it feel good to write about things that went well, you’ll have a record of what you did. That way, you’ll be able to apply it next time as well. These kinds of items (both the good and the bad) make good fodder for technical interviews. Interviewers are often keen to see what kinds of challenges you’ve overcome to show your growth potential as an engineer.

I have one example that demonstrates the good and bad of recording mistakes. I had a nasty bug when I was trying to build my Haskell project using Cabal. I remember it being a linker error that didn’t point to any particular file. I did a good job in making a mental note that the solution was to add something to the “.cabal” file. But I didn’t write down the full context or full solution. So in the future, I'll see a linker error and know I have to do something in the “.cabal” file, but I won’t be sure exactly what. So I’ll still be more likely to repeat this error than I would if I had written down the full resolution.

SUMMARY

It’s an oft-repeated mantra that practice makes perfect. But as anyone who’s mastered a skill can tell you, only good practice makes perfect. Bad or mindless practice will leave you stuck. Or worse, it will ingrain poor habits that will take more time to undo. Deliberate practice is the process of solidifying knowledge by building up tiny habits. You pick one thing to focus on, and ignore everything else. Then you learn that focus until it has become subconscious. Only then do you move on to learning other things. This approach requires a great deal of patience.

One final thing we have to understand about learning is the need to embrace the possibility that we will make mistakes. Once we have done this, we can make a plan for recording those mistakes. This way, we can learn from them and not repeat them. This will dramatically improve our pace of development.

Now you should move onto the fourth and final part of our Haskell Brain series! You'll learn about Compile Driven Learning, a specific Haskell technique for deliberate practice!

If you want to get more hands on with deliberate practice, you should download our Recursion Workbook! In addition to some content on recursion, it contains 10 practice problems. The answers start from undefined so you can build up your solutions step-by-step. It's a great way to learn deliberate practice ideas!

If you’ve never written a line of Haskell before, don’t be afraid! You should start with our Beginner's Checklist. It will walk you through installing Haskell and give you some helpful tools for starting on your Haskell journey!