
Vlad
26.10.2018
08:47:09
просто там фшарп фич быть не должно
чтобы шарпу не было больно

Artemy
26.10.2018
08:47:26
Ну это да

Google

Roman
26.10.2018
08:47:28

Artemy
26.10.2018
08:48:04
Но в гайдлайнах всё-таки написано, что нужно в классы упаковывать (хотя модуль тот же класс по факту получается, да)

Stanislav
26.10.2018
08:48:13

Artemy
26.10.2018
08:49:08
Stanislav https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/parameters-and-arguments#optional-parameters

Roman
26.10.2018
08:51:58
Нужно просто Статик класс делать, модуль в них и компилится

Artemy
26.10.2018
08:54:39
А я вот не помню, в C# все модули видны с суффиксом Module или только те, на которые соответствующий атрибут навешен?

Alexey
26.10.2018
08:56:30

Artemy
26.10.2018
08:57:25
Не, ну можно тихонечко. Если в модуле нет каррированных функций и определений всяких DU, то ничего криминального нет

Ayrat
26.10.2018
08:59:01
Так, я максимально сократил код чтобы было понятно.
Найди дедлок (внимание, гопак)
let mutable shouldExit = false
let someAlt = Alt.never()
let rec loop() =
Alt.choose [
(if not shouldExit
then someAlt ^=> loop
else Alt.never())
(if shouldExit
then printfn "Done!"
Alt.unit() //терминируем луп здесь
else Alt.never())
]
loop() <*> job { shouldExit <- true }
|> run

Vasily
26.10.2018
09:02:12
Ну допустим someAlt ^=> loop

Ayrat
26.10.2018
09:02:37
ну допустим ты прав. А почему, знаешь?

Vasily
26.10.2018
09:02:50
Ну если объяснишь хзначение оператора

Google

Vasily
26.10.2018
09:03:17
Я их плохо читаю

Ayrat
26.10.2018
09:03:35
^=> это монадический bind для альтернатив, слева альтернатива, справа функция от внутренностей альтернативы, возвращающая альтернативу

Vasily
26.10.2018
09:05:03
Такс. У тебя в лупе вызывается тот же луп вызовом альтернатив

Ayrat
26.10.2018
09:05:15
Всё так

Vasily
26.10.2018
09:05:22
Подозреваю, что виноват Alt.choose
Т.е. первый раз проходит, а дальше упс
Т.е. он пытается запустить такую же альтернативу, которую ожидает


Ayrat
26.10.2018
09:09:03
Ну нет. Но давай я поясню. Тут в чузе две альтернативы ЯКОБЫ. НО они вычисляются через if
если shouldExit false, то первый if вычисляется в then бранч -> и будет ждать альтернативу someAlt
а второй if вычислится в else и повиснет в ожидании alt.never (никогда не дождётся).
Т.е. по смыслу это Alt.choose [ someAlt; never ] ===> someAlt (а он у нас never тоже)
Хотя тут же моментально выполняется джоба которая вертает флаг shouldExit в тру и по идее мы могли бы выйти, но луп уже отбросил проверку флага и висит на ожидании альтернативы которая не выполнится
Вот фикс без дедлоков:
let shouldExit = IVar<unit>()
let someAlt = Alt.never()
let rec loop() =
Alt.choose [
(if not (IVar.Now.isFull shouldExit)
then someAlt ^=> loop
else Alt.never())
shouldExit ^-> fun _ ->
printfn "Done!" //терминируем луп здесь
]
loop() <*> shouldExit *<= ()
|> run

Vasily
26.10.2018
09:10:03
Логично

Ayrat
26.10.2018
09:10:09
почему он работает
теперь мы делаем флаг через конкурентный примитив IVar, который тоже альтернатива кстати
и мы можем в Alt.choose запихнуть явно ожидание флага shouldExit

Vasily
26.10.2018
09:10:45
Вообще, конечно, стремная альтернатива
Там нельзя написать просто if (notExist ) then loop else Alt.unit() ?

Ayrat
26.10.2018
09:11:17
т.е. теперь наш Alt.choose раскрывается в
Alt.choose [ someAlt; shouldExit ]
и даже если он никогда не дождётся someAlt, то когда-нибудь, даже с рейс кондишном он дождётся shouldExit и выйдет удачно
Погреешь воздух сильно)

Vasily
26.10.2018
09:11:53
Зима близко (с)

Ayrat
26.10.2018
09:14:01
Короче, мораль, альтернативы это хорошо, но если есть какое-то условие, то его надо тоже в альтернативы запихивать, благо они около бесплатные

Vasily
26.10.2018
13:25:16
Какое интересное чтиво: https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1063-support-letbang-andbang-for-applicative-functors.md

Google

Stanislav
26.10.2018
13:52:14
Помогите пожалуйста, почему так?
let result = false
let saySome =
printfn "some"
if result then
saySome
printfn "some2"
()
> some
Как этого избежать? Оно вообще ничего делать же не должно..

Vasily
26.10.2018
13:53:45
Думаете вы

Stanislav
26.10.2018
13:54:23
Чем больше будет разработчиков на F# тем чаще оно будет оказываться в продах компаний )

Vasily
26.10.2018
13:54:28
Вычисление saySome произойдет сразу

Pavel
26.10.2018
13:54:34

Stanislav
26.10.2018
13:55:35

Vasily
26.10.2018
13:56:16
Это называется мемоизация

Igor
26.10.2018
14:04:07

Vasily
26.10.2018
14:04:44
Возможно

Grigoriy
26.10.2018
14:05:44

Artemy
26.10.2018
14:06:41
Stanislav let saySome = printfn "Some" по смыслу ближе к Сишарповскому var saySome = ..., в то время как let saySome() = ... это уже более похоже на void saySome() { ... }. Ну это так, чисто для упрощения понимания.

Ayrat
26.10.2018
14:06:55

Grigoriy
26.10.2018
14:07:16

Ayrat
26.10.2018
14:07:24
Ну мы не знаем что вернёт ... !

Artemy
26.10.2018
14:07:40
Разве void- не самое похожее на unit?
В С# же нету чего-то более подходящего

アレクセイ
26.10.2018
14:08:09
void не композится

Ayrat
26.10.2018
14:08:19
т.е. принял unit, вернул unit

Artemy
26.10.2018
14:08:28

Google

Ayrat
26.10.2018
14:08:56
в общем, всё ок)

Stanislav
26.10.2018
14:09:22
Офигеть, я думал, что let some = ... и let some () = ... одно и то же ))

Artemy
26.10.2018
14:09:24
Я тут пытался упростить понимание, вообще-то.)

Stanislav
26.10.2018
14:09:53

Ayrat
26.10.2018
14:09:59

Artemy
26.10.2018
14:10:13
Как написали выше, () aka unit - это значение
Следует привыкнуть так понимать

Grigoriy
26.10.2018
14:10:30
По-моему вы тут тока усложняете
А человек хотел упростить

Vasily
26.10.2018
14:10:52
Это не к нам
Кароч
Если функция без параметров
Она вычисляется сразу и мемоизируется

Artemy
26.10.2018
14:13:22
(т.е. её тело не будет срабатывать каждый раз при вызове)

Ayrat
26.10.2018
14:13:24
Да, проще будет если учесть что в F# всё функция.
Даже если это
let a = 1
потому что можно написать и такое
let f =
let container = [1;2;3;4;5]
fun x -> List.contains x

Vasily
26.10.2018
14:15:00
Ну как бы я не помню, чтобы в фшарп было разделение на функции и и значения

Ayrat
26.10.2018
14:15:18
в этом примере f это точно функция от одного параметра x, но она очень хитро имеет внутри мемоизированный контейнер

Google

Ayrat
26.10.2018
14:15:46
там с value restriction траблы начинаются

Vasily
26.10.2018
14:15:59
Пример в студию

Ayrat
26.10.2018
14:16:22
Подожди. мне надо поработать слегка

Vasily
26.10.2018
14:16:43
Ох уж эта НБА

Ayrat
26.10.2018
14:17:56
Да полный пиздец
И именно НБА, да

Vasily
26.10.2018
14:18:05
Кто на этот раз?
Хммм, а вот тут хотят линзы в рекорд экспрешны впилить: https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md

Artemy
26.10.2018
14:19:46
Как написали выше, () aka unit - это значение
Немного подумал и поправлюсь. unit — это, считай, множество (тип), в котором есть лишь один элемент — (). Потому, в принципе, можно с таким же успехом в качестве параметра передавать хоть число, хоть строку и не использовать этот параметр в теле. Результат будет такой же.
Stanislav ↑

Vasily
26.10.2018
14:20:31
В теории, можно извратиться еще с генериком

Stanislav
26.10.2018
14:23:17
Ухх, прям хорошо пошло, второй день ковыряю)

Vasily
26.10.2018
14:24:26
Ну дальше будет интереснее, но придется систему мышления менять

Stanislav
26.10.2018
14:25:40
Ещё меня поразило то, что порядок декларации функций не от балды
И option

Vasily
26.10.2018
14:26:04
Ну это-то как раз дисциплинирует
И заставляет думать при проектировании
Результатом является то, что код очень легко читать

Artemy
26.10.2018
14:26:34
Да, не даёт хаос в коде устроить

Vasily
26.10.2018
14:26:41
Всегда сверху вниз

Stanislav
26.10.2018
14:26:56
В С# то я наоборот пишу сверху самый сок, а ниже уже прайват методы служебные