-
Notifications
You must be signed in to change notification settings - Fork 266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
jun3/haskell: fix questions and add some new #341
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 на верхнем уровне добавлять не стал, у нас эта тема есть на мидле, так что внесу туда.