
Roman
26.09.2018
12:55:35

Ayrat
26.09.2018
12:56:08

Friedrich
26.09.2018
12:56:10
Народ, а как быстро вы перешли с C# на F#? И не тянет ли обратно в ООП?
Я сперва писал на F# как на «C# с немножко другим синтаксисом», но сразу начал пользоваться модулями, локальными и модульными функциями и другими плюшками, которые показались уместными. Ну а потом уже начал пользоваться более суровыми штуками, каррированием, всякими fancy-операторами и пр.
С теми, кто говорит, что от старого ООП подташнивает, согласиться не могу — лично у меня нормально получается работать и с ООП-, и с ФП-кодом :)

Ivan
26.09.2018
12:57:30
Старого = это того, на котором писал сам до знакомства с F#

Google

Maxim
26.09.2018
12:57:30
Я сперва писал на F# как на «C# с немножко другим синтаксисом», но сразу начал пользоваться модулями, локальными и модульными функциями и другими плюшками, которые показались уместными. Ну а потом уже начал пользоваться более суровыми штуками, каррированием, всякими fancy-операторами и пр.
С теми, кто говорит, что от старого ООП подташнивает, согласиться не могу — лично у меня нормально получается работать и с ООП-, и с ФП-кодом :)
А код на C# претерпел какие-то изменения? ? А то я читал много где, что после освоения ФП (хаскель) кодишь красивее ?

Friedrich
26.09.2018
12:58:13
Интересно, что я очень долгое время не пользовался при этом SRTP (но потом уже начал и штука полезная). И REPL до сих пор практически никогда не пользуюсь. Поначалу иногда тыкался, чтобы быстро проверять синтаксис. А сейчас уже нет.
Наверное, я немного нетипичный в этом отношении F#-программист.

Ivan
26.09.2018
12:58:25

Friedrich
26.09.2018
12:59:10
Я надеюсь, что мой код C#-программистам читать не очень сложно.
В качестве примера — вместо выбрасывания исключений откуда не попадя в нужных местах прикручиваю вот такой функтор: https://github.com/ForNeVeR/wpf-math/blob/4da8b0a91db1e5cad04a4126c937e7ce37bffc9b/src/WpfMath/Utils/Result.cs

Kirill
26.09.2018
13:00:31

Friedrich
26.09.2018
13:00:46
(за свойство Value, которое кидается исключениями, меня уже критиковали, но я твёрдо уверен, что так и должно быть)

Vlad
26.09.2018
13:00:58
как бы пишется код на F#, но чувство что "что-то не то" не покидает

Friedrich
26.09.2018
13:01:19
Разве что изучишь искусство получения лещей :)

Kirill
26.09.2018
13:01:26

Google

Friedrich
26.09.2018
13:02:16
А для меня написание F#-штук — в том числе и драйвер для изучения новых полезных концепций в программировании.

Kirill
26.09.2018
13:02:24

Friedrich
26.09.2018
13:02:44
И вообще ни одной парадигмы не сломал!
Просто отрастил новые.

Vlad
26.09.2018
13:03:14

Kirill
26.09.2018
13:03:21
не более
Просто решай какие нибудь задачи в ФП подходе и собирай грабли
(По крайней мере лучше способа осиливать новые способы формирования логики я не нашёл до сих пор)

Vlad
26.09.2018
13:04:14
кстати
попробовал темплейт от сайма для провайдеров типов
там теперь прям из студии получилось тест с провайдером задебажить - разве так раньше можно было?

Maxim
26.09.2018
13:09:09
Из ФП я стараюсь использовать "чистые функции" ? Пока больше вроде ничего не прижилось ?

Friedrich
26.09.2018
13:10:25

Vlad
26.09.2018
13:11:21

Friedrich
26.09.2018
13:11:32
Вернее, не совсем в тестах
Кейс с двумя солюшенами остался, если ты девелопишь провайдер, а рядом его используешь на практических примерах
Если ты просто запускаешь юнит-тесты — это обычный кейс, и он работает как всегда в студии.

Google

Friedrich
26.09.2018
13:12:53
А вот если ты хочешь рил использовать провайдер в девелопмент-среде — тогда тебе надо второй солюшен. Потому что с одним солюшеном все очень хреново.

Vlad
26.09.2018
13:53:59

Grigoriy
26.09.2018
13:54:40
Привет, Иван!

Ivan
26.09.2018
13:55:06

Grigoriy
26.09.2018
13:55:10
Привет, Валера!
Интересуетесь Ф#?

Никос
26.09.2018
14:01:42
Кревед

Grigoriy
26.09.2018
14:05:05

Dany
26.09.2018
14:08:28
Всем привет. Я новенький в F#. Подскажите кто знает, почему функции logResult'' и logResult имеют разную сигнатуру?
let logResult res =
match res with
| Ok(x) -> log.Info("Partial result: " + x.ToString())
| _ -> ()
res
let logResult' logInfo res =
match res with
| Ok(x) -> logInfo("Partial result: " + x.ToString())
| _ -> ()
res
let logResult'' = logResult' (fun x -> log.Info(x))
logResult: Result<'a,'b> -> Result<'a,'b>
logResult'': Result<obj, obj> -> Result<obj, obj>

Valera
26.09.2018
14:17:24

Vasily
26.09.2018
14:18:21

Ivan
26.09.2018
14:20:04
let logResult' logInfo res =
match res with
| Ok(x) -> logInfo("Partial result: " + (box x).ToString())
| _ -> ()
res
ToString - метод obj, вот он и выводит тип как obj

Dany
26.09.2018
14:21:33
Нужен пример вызова функций
extractSongIdFromLink url
|> logResult
|> Result.bind(createGMPreviewLink)
|> logResult
|> Result.bind(loadDoc)
|> logResult
и т.д.
extractSongIdFromLink, createGMPreviewLink, loadDoc возвращают разные Result типы

Vasily
26.09.2018
14:21:45
Кстати, @ijsgaus прав

Dany
26.09.2018
14:22:13

Vasily
26.09.2018
14:22:44
А с чем должно выводиться?

Dany
26.09.2018
14:22:58
Result<'a,'b> -> Result<'a,'b>
хотелось бы

Klei
26.09.2018
14:23:47

Google

Klei
26.09.2018
14:24:15
Если добавить параметр который будет передан тут же, то функция останится дженериком.
let logResult'' p = logResult' (fun x -> log.Info(x)) p

Pavel
26.09.2018
14:25:55

Ivan
26.09.2018
14:26:24

Pavel
26.09.2018
14:27:44
обычные циклы. твои тайлрекурсион в мутабельность не умеют

Klei
26.09.2018
14:27:53

Dany
26.09.2018
14:28:06

Ivan
26.09.2018
14:28:06
Seq.iter

Klei
26.09.2018
14:28:11
Seq.iter
Есть случаи, когда надо раньше времени выйти. И которые через стандартные функции не решаются.
Ну либо я рукожоп.

Ivan
26.09.2018
14:28:51
Это просто для понимания, откуда компилер типы берет
Seq.filter, Seq.takeWhile

Klei
26.09.2018
14:30:08

Dany
26.09.2018
14:30:15

Ivan
26.09.2018
14:31:52

Grigoriy
26.09.2018
14:32:45

Pavel
26.09.2018
14:34:36

Klei
26.09.2018
14:36:13

Google

Grigoriy
26.09.2018
14:36:41

Dany
26.09.2018
14:39:17

Klei
26.09.2018
14:44:27
Seq.filter, Seq.takeWhile
Как выглядит кошерная обработка случая?:
Сфолдить все элементы удовлетворяющие условию пока (если) не встретишь бракованный.
После чего сфолдить свернутое и этот самый бракованный, если таковой существует.
Затем выдать результат.
// Подвоха в вопросе нет. Прост каждый раз сталкиваясь с этой задачей пилю новый велосипед.

Vladimir
26.09.2018
14:50:27
Через Seq.filter находишь все небракованные, дальше их обрабатываешь)

Grigoriy
26.09.2018
14:50:58
Фильтром можно найти только первый бракованный, но его позиция в исходной последовательности потеряется

Vladimir
26.09.2018
14:52:26
Ну тогда Seq.iter ищешь первый бракованный)
но не катит так как два раза придется обходить

Grigoriy
26.09.2018
14:53:39
Да :) многопроходное придумывается относительно просто
Но что если на входе - генератор и к началу не вернуться?

Vladimir
26.09.2018
14:56:47
ну тут конечно можно подискутировать на тему так ли надо останавливаться на первом невалидном)
но вообще же есть вот такое решение
https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/loops-while-do-expression
тот же брейк посути

Klei
26.09.2018
14:59:04
Мы говорили про рекурсии и стандартные функции.
Щас я в большинстве случаев через while отрабатываю.