@Fsharp_chat

Страница 315 из 772
Vasily
19.09.2017
15:05:31
Как я понял , тайпклассы - способ навесить дополнительный функционал на некоторое множество типов

Aleksey
19.09.2017
15:05:48
Имплиситы умеют не всё, что умеют тайпклассы. И у имплиситов полно родовых травм - та же зависимость от порядка импортов

Friedrich
19.09.2017
15:06:07
Vasily
19.09.2017
15:06:30
Я бы сказал, в конкретном языке

Google
Aleksey
19.09.2017
15:06:30
Тайпклассы, это возможность генерализовать поведение для некоторой группы типов, не имеющих ничего общего в общем случае

Friedrich
19.09.2017
15:06:31
У тайпклассов тоже есть такая проблема, кстати (по крайней мере, раньше в Haskell была) — нельзя было их отдельно импортировать из модуля. Сейчас починили?

Но это проблемы не принципиальные, а просто не очень большие (как по мне) дырки в конкретных реализациях.

Aleksey
19.09.2017
15:07:17
Импортировать тайпкласс без инстансов нельзя, т.к. это ломает вывод типов и вообще приводит к неопределённому поведению

Friedrich
19.09.2017
15:07:38
Вернее, нельзя было импортировать инстансы отдельно от остального из модуля.

Vasily
19.09.2017
15:08:03
Хотя, конечно, есть впечатление, что мы можем и до фри монад договориться... но все равно интересно

Friedrich
19.09.2017
15:08:16
Например?
Я те щас покажу пример

Aleksey
19.09.2017
15:08:23
Пример: ты говоришь, что есть нечто, потенциально сериализуемое в JSON. Это нечто всегда имеет метод toJSON

При этом сериализоваться могут многие типы

В т.ч. и не твои

Vasily
19.09.2017
15:09:01
А где правила сериализации прописываются и детали?

Google
Friedrich
19.09.2017
15:09:07
Простой и понятный доброму человеку пример: https://github.com/ForNeVeR/EvilPlanner/blob/dd44d11895b3d61b592fb4599117367ed57c2222/EvilPlanner.Logic/DatabaseExtensions.fs#L15-L33

Aleksey
19.09.2017
15:09:08
И соль тайпклассов в том, что реализация поведения лежит отдельно от типа, либо отдельно от класса

Вощм, фишка в том, что можно дореализовать данное кем-то поведение для своих типов. И дореализовать твоё поведение для чужих типов. Не имея исходников

А компилятор следит за тем, чтобы некое конкретное поведение для некоего конкретного типа было реализовано ровно один раз (если реализовано вообще, конечно)

Friedrich
19.09.2017
15:11:05
Простой и понятный доброму человеку пример: https://github.com/ForNeVeR/EvilPlanner/blob/dd44d11895b3d61b592fb4599117367ed57c2222/EvilPlanner.Logic/DatabaseExtensions.fs#L15-L33
У меня есть типы IQueryable<T> и DbRawSqlQuery<T>. Я хочу функцию singleOrDefaultAsync, которая бы делала понятно что для обоих типов. При этом у меня на одном типе есть обычный метод this.SingleOrDefaultAsync, а на другом типе есть статический экстеншен QueryableExtensions.SingleOrDefaultAsync (т.е. через SRTP это разрулить невозможно). Оба типа — не мои. Но я хочу, чтобы мой код работал прозрачно вне зависимости от того, какой из этих типов туда передали.

У меня есть типы IQueryable<T> и DbRawSqlQuery<T>. Я хочу функцию singleOrDefaultAsync, которая бы делала понятно что для обоих типов. При этом у меня на одном типе есть обычный метод this.SingleOrDefaultAsync, а на другом типе есть статический экстеншен QueryableExtensions.SingleOrDefaultAsync (т.е. через SRTP это разрулить невозможно). Оба типа — не мои. Но я хочу, чтобы мой код работал прозрачно вне зависимости от того, какой из этих типов туда передали.
...я таки умудрился сделать это на SRTP (спрашивал на SO и мне подсказали, как делать правильно), но у моей реализации проблема. Каждый раз, когда мне нужно добавить новый тип в набор типов, поддерживаемых функцией singleOrDefaultAsync, мне нужно идти вот в этот самый файл и туда вносить исправления. В общем-то, нарушается SRP. У нормальных тайпклассов бы такого ограничения не было, и я бы мог писать реализации для тайпкласса где угодно — в любом файле, модуле, сборке. И моя функция singleOrDefaultAsync бы с таким типом могла работать.

Arseniy
19.09.2017
15:15:40
ну кароче речь о том, какой из маханизмов для ad-hoc polymorphism лучш

Friedrich
19.09.2017
15:15:57
Да дайте хоть какой-нибудь :)

Evgeniy
19.09.2017
15:21:49
о/

Алекс
19.09.2017
15:22:29
Щас будет реклама отдыха))

Arseniy
19.09.2017
15:22:53
ну блин, ооп оно такое. если у тебя встает задача подобного вида, то ковыляешь в сторону объектов-компаньонов. если у тебя есть объекты типов T1 и T2, для которых нужно одинаковое поведение, и они не унифицированы. тип фигачишь IQueryExecutor<T> и лепишь имплементации для T1 и T2

Friedrich
19.09.2017
15:23:04
Щас будет реклама отдыха))
Если будет — разберёмся. А до тех пор у нас действует презумпция.

ООП — да, оно такое. Но есть же SRTP, который прям самым естественным образом эту задачу решает.

Единственная причина, по которой я не могу его использовать — это вот эта проблема расширябельности.

Arseniy
19.09.2017
15:24:04
ну вон выше про имплиситы скалы была речь как я понял. там чуваки научились полуавтоматически такие объекты везде протаскивать.

Friedrich
19.09.2017
15:24:08
Она даже не выглядит очень уж сложной

Arseniy
19.09.2017
15:24:11
я не знаю, что такое SRTP

Friedrich
19.09.2017
15:24:17
И совсем напрасно.

Стоит ознакомиться.

Google
Friedrich
19.09.2017
15:24:40
SRTP это инлайн, кароч.

Собственно, метапрограммирование на F# — это как раз про SRTP и тайп-провайдеры. Не про ООП.

Arseniy
19.09.2017
15:25:55
а расшифровывается как?

Friedrich
19.09.2017
15:26:06
Statically Resolved Type Parameters

Arseniy
19.09.2017
15:26:35
а, ясно.

ну кароче, это приконьно, но костыль уровня c++.

Friedrich
19.09.2017
15:27:48
Ну, если говорить про C++20 (концепты).

«Костыль» уровня блидинг-эдж метапрограммирования на C++. Неплохо, я б хотел такой костыль.

А, подождите, он же у меня есть ?

Arseniy
19.09.2017
15:28:25
по-моему, шаблоны плюсов уже давно мощнее чем SRTP

Friedrich
19.09.2017
15:28:32
Они про другое.

Концепты про то же самое.

Шаблоны практически отсутствуют в системе типов, они на другом уровне.

А вот SRTP присутствуют в системе типов.

Vasily
19.09.2017
15:29:09
@fvnever я так и не понял, как бы тебе помог тайпкласс в твоем случае

Friedrich
19.09.2017
15:29:14
Поэтому возможности инструментов разные.

Arseniy
19.09.2017
15:29:29
ну так и SRTP отсутствует. инлайн и полтора констрейна.

Friedrich
19.09.2017
15:29:31
@fvnever я так и не понял, как бы тебе помог тайпкласс в твоем случае
Я бы смог добавлять поддержку новых типов в свою функцию из других сборок, например.

Vasily
19.09.2017
15:29:33
Если у тебя один статический метод, второй инстанс

Friedrich
19.09.2017
15:29:49
ну так и SRTP отсутствует. инлайн и полтора констрейна.
Ну, это и есть SRTP. Если у тебя есть какие-то ещё определения для SRTP — поделись, пожалуйста.

Google
Vasily
19.09.2017
15:30:13
Где прописывается поведение, когда надо вызвать статический метод, а когда нет?

Arseniy
19.09.2017
15:30:21
ну и что тут про систему типов?

Friedrich
19.09.2017
15:30:36
ну и что тут про систему типов?
Посмотри тип какой-нибудь SRTP-функции.

Давай вот на примере.

Arseniy
19.09.2017
15:31:06
посмотри на какой-нибудь шаблон. тоже самое. только там выбор средств побогаче

Friedrich
19.09.2017
15:31:20
C++: template<class T> auto foo(T& x, T& y) -> decltype(x + y) { return x + y; }

Какой тип у этой функции?

Вообще-то хрен его знает, какой. Никакого нету.

Но про оператор + в этом типе ничего не сказано.

А теперь то же самое на F#: let inline foo a b = a + b

Какой тип у этой функции? Правильно — такой, который требует оператор + между a и b.

Arseniy
19.09.2017
15:33:35
и ф чем ты видишь концептуальную разницу?

Vasily
19.09.2017
15:33:37
Кстати

Friedrich
19.09.2017
15:33:38
Ну, на C++ нам там повезло, конечно, что у меня возвращаемый тип с плюсом

Можно другой пример выдумать, без decltype, где вообще непонятно будет.

Vasily
19.09.2017
15:33:54
Если я ниже напишу let x = foo 2 3

Vasily
19.09.2017
15:34:01
Какой тип выведет?

Friedrich
19.09.2017
15:34:09
2 и 3 — инты.

Google
Vasily
19.09.2017
15:34:34
А если функция обобщенная нужна?

Friedrich
19.09.2017
15:34:45
Тогда будь добр, пиши обобщённо.

Например, будет работать let inline foo2 a b = foo a b, тут будет правильный тип.

Vasily
19.09.2017
15:35:25
Если уж упарываться по полной, то надо 'a->'a->'b

Friedrich
19.09.2017
15:35:34
Только не ', а ^

(хотя они тут взаимозаменяемы, кажется?)

Vasily
19.09.2017
15:35:47
Да, ты прав

Хотя надо проверять

Arseniy
19.09.2017
15:36:10
Какой тип у этой функции? Правильно — такой, который требует оператор + между a и b.
тоже самое и в плюсах. это уже чисто аспект реализации. принципиальной разницы нет. но типо в фишарпе это проверить типизатор, а в плюсах по факту раскрытия чекнется.

Vasily
19.09.2017
15:36:35
В плюсах развернется препроцессором

Насколько я помню

Friedrich
19.09.2017
15:36:42
Нет!

Vasily
19.09.2017
15:36:47
В местах конкретного вызова

Не?

Friedrich
19.09.2017
15:36:51
Неееет

Vasily
19.09.2017
15:37:08
Хммм... всегда считал, шо шаблоны - те же макросы

Friedrich
19.09.2017
15:37:19
В плюсах для этого дела совершенно отдельный механизм, который отдельными аспектами напоминает препроцессор, но на самом деле вообще другое.

Страница 315 из 772