-
Notifications
You must be signed in to change notification settings - Fork 264
jun3/haskell: fix questions and add some new #341
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
7c47b0c
to
4bc205c
Compare
4bc205c
to
1b875a5
Compare
1b875a5
to
073d64a
Compare
@@ -127,7 +127,7 @@ | |||
* `ScopedTypeVariables` | |||
* What is the main goal of this extension? | |||
* Higher ranked types | |||
* What is a "rank" of a function? | |||
* What is a higher rank function? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вопрос "как определяется ранг функции", на мой взгляд - вполне корректный и не нуждается в удалении. Можно пояснить, почему он заменяется на "что такое функция высшего ранга"? Это более слабый вопрос, поскольку в нём не уточняется, например, чем именно отличается функция 2-го ранга от функции 3-го.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Чтобы определять числовой ранг функции, у нас не хватает источника. В доках по хаскелю не объяснено, как по сигнатуре определить ранг.
Стас говорил, что определение ранга непростое, и мы подумали, что оно на практике не нужно. Достаточно отличать первый ранг от всех остальных, а уж какой он - третий или четвертый - не влияет на то, как применять RankNTypes.
backend/junior-3/haskell.md
Outdated
* What is the function `seq` (and operator `$!`)? | ||
* What is the function `deepseq` (and operator `$!!`)? | ||
* Could using `seq` change the returned value of the function? | ||
* What is the expression result: ``(a + b) `seq` ((a + b) : list)``? Why? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не очень понятно к чему относится второй вопрос Why?
, может его раскрыть?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вопрос, почему результат именно такой, какой он есть :). Why does it happen?
- может так?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Грамматическая придирка - в текущем виде, кодовая цитата относится к слову "result", то есть вопрос буквально звучит как "Какой у выражения результат: (a+b) `seq` ((a+b) : list)
". Я думаю, будет более верно сформулировать как "What is the result of the expression: <>".
А вообще, мне не совсем понятно, что именно ожидается в ответе на этот вопрос - ну, результатом будет (a+b) `seq` ((a+b) : list)
, duh. Ну, можно переписать это как let x = a+b in x `seq` (x:list)
Может, лучше вообще спрашивать не про "результат", а про поведение в конкретных ситуациях - под evaluate
и evaluateNF
, если в a
боттом, если в a
стоит trace
или unsafePerformIO
, если на результат ещё сверху повесили trace
или unsafePerformIO
, и продвинутый вопрос - если мы в реализации (+)
впишем trace
или unsafePerformIO
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
С придиркой согласен, переделаю.
Насчет ответа на вопрос: да, здесь вопрос скорее о поведении, а не о результате - что в этом выражении seq
бесполезен, и надо объяснить почему. Кстати, источника не хватает.
а про поведение в конкретных ситуациях - под evaluate и evaluateNF, если в a боттом, если в a стоит trace или unsafePerformIO, если на результат ещё сверху повесили trace или unsafePerformIO, и продвинутый вопрос - если мы в реализации (+) впишем trace или unsafePerformIO.
Про evaluate не понял. Про unsafePerformIO пусть отвечающий рассказывает в вопросе про то, может ли seq
изменить результат выражения :). Там прямо напрашивается. Или можно явно спросить об этом, но мне кажется, изначальный смысл вопроса был в другом.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Поправил вопрос, но так и не нашел источник, где я видел ответ. Может, потом. Вы знаете ответ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если referential transparency соблюдается - то выражение семантически эквивалентно let x = a+b in x `seq` (x:list)
. По факту - компилятор имеет полное право как объединить одинаковые выражения, так и оставить их раздельными.
let a = unsafePerformIO (print "A" >> pure 1)
let b = 2
let z = (a + b) `seq` ((a + b) : list)
print "Start"
zh : _ <- evaluate z
print "Mid"
void (evaluate zh)
print zh
print "End"
На код выше компилятор может написать как Start // A // Mid // A // 3 // End
, так и Start // A // Mid // 3 // End
- допустимы оба варианта. Скорее всего, GHC будет работать по первому с -O0
и по второму с -O2
.
Кстати о трейсе, как вам такое предложение - перенести весь блок "Debugging" перед "Laziness", и в блоке про ленивость добавить задачек с использованием трейса, например: let a = trace "a" (trace "head a" 10 : trace "tail a" [])
let b = trace "b" (Just (trace "fromJust b" 20))
let c = trace "c" (trace "c1" () `seq` trace "c2" ())
let d = trace "d" (Just (trace "d1" () `seq` trace "d2" ()))
let e = trace "e" (let !e1 = trace "e1" () in trace "e2" ())
let f = trace "f" (let Just !f2 = trace "f1" (Just (trace "f2" (Right (trace "f3" ())))) in trace "f4" (Just (trace "f5" f2)))
-- Assuming a..f were never evaluated before, what would `void (evaluate a)` print?
-- What would `void (evaluateNF a)` print?
-- Among the lines printed, are there any restrictions on their order of appearance? |
Можно. А зачем столько строк, если используется только первая? Если это подвох, то хватило бы и двух строк. |
Все три вопроса повторяются для каждой строки. |
Для них сделать бы отдельные файлы уже, а то слишком много получается задачек. Можно их как дополнительные для понимания дать. Мне кажется уже базовые знания с текущими задачами тестируются. |
Слишком много упражнений, некоторые сложно прочитать, лень будет над ними думать. Так как ответ элементарно узнать в репле, это рискует быть самым популярным способом решения :). Достаточно по одному примеру на каждое маленькое знание, наличие которого мы хотим проверить. По-моему, и первой строки хватило бы, на понимание ленивого вычисления в целом. Многие вещи мы уже спрашиваем в других вопросах - про bang patterns в let, про seq. |
Детально по примерам:
Согласен, на понимание ленивых вычислений годится.
В принципе то же самое, только с Maybe вместо списка, думаю, что избыточно.
Вопрос на понимание seq, который мы уже спрашиваем, но здесь надо знать один нюанс, про порядок вычисления параметров seq. Можно добавить вместе с источником про порядок вычислений в seq.
Ленивые вычисления (первый пример) + seq, избыточно.
Bang patterns in let - про это уже есть вопрос, избыточно.
Ленивые вычисления + bang pattern in let, избыточно и уж очень сложно прочитать. Так что два примера я готов добавить, а остальные примеры думаю, что не стоит, они дублируют существующие вопросы и примеры. Если хочется именно задачки, на прокачку навыков предсказания работы ленивых вычислений (только зачем? Кажется, это не особо нужный навык), то мне кажется, надо что-то поинтереснее (только как тут сделать интереснее? :)). Последний пример, с 4 уровнями скобок, я даже и не пытался понять. |
Идею про упражнения я вынес в issue #357 , не хочется добавлять их в этот ПР, а то он еще полгода не смержится. Внес некоторые финальные правки, посмотрите пожалуйста. |
Некоторые исправления, которые обсуждали во время моей сдачи, они описаны в #309.
Про синонимы стратегий вычисления лень было думать. Это надо источники перечитывать и думать, что выпилить, что оставить, как сформулировать вопросы. Может, потом :).
Про irrefutable patterns в let/where на верхнем уровне добавлять не стал, у нас эта тема есть на мидле, так что внесу туда.