
Mikhail
15.10.2017
17:30:00
Подскажите, пожалуйста, как правильно называется эта фича?
type FooType = {Id: int}
type AnotherFooType = FooType

Oleg
15.10.2017
17:33:24

Mikhail
15.10.2017
17:34:07
Т.е. это все тот же тип?

Evgeniy
15.10.2017
17:34:27

Google

Mikhail
15.10.2017
17:34:33
Жаль(

Oleg
15.10.2017
17:34:45
нет, алиас, он как бы только в пределах компилятора существует

Evgeniy
15.10.2017
17:35:35

Oleg
15.10.2017
17:36:13
Это и подразумевается под "тот же тип". :)
:) да, здесь чисто терминологическое расхождение :) Я поторопился ответить, прочитав "все же тип". Правильный ответ - это конечно "да", то есть они неотличимы для системы типов

Evgeniy
15.10.2017
17:37:31
Жаль(
Если хочется новый настоящий тип, то можно сделать обертку.

Mikhail
15.10.2017
17:38:29
У меня проблемма в том, что есть много тиопов запросов, запрос я представил как Record
type AbstractQuery = { MethodModule: string; MethodName: string; QueryParams: IDictionary<string, string>; ApiVersion: float }
Все данные для всех запросов одинаковые, но я хочу ограничить с помощью типизации методы, которые можно применять к запросам
И пока не придумал ничего лучше, как сделать это с помощью композиции Record'ов
type MessageQuery = { Query: AbstractQuery }
type AccountQuery = { Query: AbstractQuery }
type GroupQuery = { Query: AbstractQuery }
Может, у кого-то есть идеи, как сделать лучше?

Ivan
15.10.2017
17:41:35
Проще:
type MessageQuery = MessageQuery of AbstractQuery

Oleg
15.10.2017
17:41:55
если обернуть типа type GetQuery = GetQuery of AbstractQuery, то вроде нормально получается

Evgeniy
15.10.2017
17:43:24
Да, еще можно навесить на тип аннотацию [<Struсt>], чтобы лишних аллокаций не было.

Oleg
15.10.2017
17:43:59
деконструирование можно сразу в сиигнатуре метода сделать let SomeMethodOnMessage (MessageQuery query) = ... process as abstract query

Google

Mikhail
15.10.2017
17:44:10
А из-за чего будут лишние аллокации?

Evgeniy
15.10.2017
17:44:33
А со [<Struct>] будет почти zero-cost абстракция. :)

Ivan
15.10.2017
17:46:00
Если не надо прокидывать в другие методы
Тут палка о двух концач ? - можно потерять на боксинге + аллокация

Oleg
15.10.2017
17:47:04
может это преждевременно, о такой оптимизации думать? Может там Сиквел-запросы

Evgeniy
15.10.2017
17:47:21
Каждую такую оптимизацию нужно бы подтверждать в конкретных случаях бенчмарками.

Mikhail
15.10.2017
17:50:17
Благодарю! Теперь для C# это разные классы
Проще:
type MessageQuery = MessageQuery of AbstractQuery

Sergey
15.10.2017
17:58:42

Mikhail
15.10.2017
18:04:57
Мне нужно ограничить пользователю методы, применимые к различным типам запросов. На MessageQuery в параметры можно добавить body, в остальные нельзя

Vasily
15.10.2017
18:30:09
Несколько билдеров

Mikhail
15.10.2017
18:34:47
Well, thats an idea

Vladimir
15.10.2017
19:49:40
https://stackoverflow.com/a/18383229/1780648
вот это должно было помочь но нет =) когда пишешь m -> m.Id ругается компилятор, т.к. указан object в типе результата а если написать m -> box m.Id тогда невалидный экспрешн. Патовая ситуация, похоже F# не совместим с fluent api
Так, сорри за панику, получилось обойти =) в функции хелпере надо на вход 'a и 'b на вход принимать, а на выходе уже 'a и obj

Снежный
16.10.2017
06:18:50
Всем привет. Кто-нибудь использовал F# FAKE Wix?
Интересует момент создания ярлыков. Никак не могу вкурить как их создать

Google

Vasily
16.10.2017
07:24:35
Ну это скорее по виксу вопрос

Aminion
16.10.2017
07:35:50
Как называются функции, которые конвертируют один тип монад в другой?

Evgeniy
16.10.2017
08:08:09
Или что ты имеешь в виду?
TIL В F# сборках хранится информация о type aliases.
Почему-то не задумывался об этом раньше.

Roman
16.10.2017
11:03:51
Доброго дня, товарищи!
Такой вопрос - вы тут недавно ковырялись в провайдерах и мне бы хотелось знать, какие неожиданные или неочевидные штуки вы при этом встречали?
Как обычно, интересуюсь с корыстными целями использования в докладе :)

Evgeniy
16.10.2017
11:05:11
@fvnever @Dolfik

Nikolay
16.10.2017
11:05:42
Отвечает Господин Фридрих

Friedrich
16.10.2017
11:05:49

Nikolay
16.10.2017
11:06:16

Friedrich
16.10.2017
11:06:39
А я думать не стану, не приучен!

Pavel
16.10.2017
11:07:07

Friedrich
16.10.2017
11:07:36
Что конкретно беспокоит?

Andrew
16.10.2017
11:08:05
что вместо 'C подставился obj?

Pavel
16.10.2017
11:08:14
да
понятное дело, если типы не указаны, возможен вывод obj

Evgeniy
16.10.2017
11:09:17
Контекста не хватает.

Pavel
16.10.2017
11:09:52
боюсь, быстро предоставить минималистичный пример не смогу =\

Evgeniy
16.10.2017
11:10:02
Откуда должен тип 'C вывестись? Из какого контекста?

Google

Pavel
16.10.2017
11:10:41
type MessagingManager<'C> (...) =
...
let sender = MailboxProcessor.Start((fun (inbox: MailboxProcessor<SenderCommand<'C>>) ->
и сейчас, конечно же, на дженерик-параметр класса интеллисенс ругается, что он может быть только obj

Evgeniy
16.10.2017
11:13:33

Pavel
16.10.2017
11:14:53
имеется это в виду?

Evgeniy
16.10.2017
11:16:20
Нет. Что ты хочешь сделать? :)
Может фабрику агентов с возможностью указать тип в SenderCommand?

Pavel
16.10.2017
11:20:01
Не фабрику, просто при инициализации класса должен запускаться агент, принимающий сообщения, параметризованные дженериком класса

Evgeniy
16.10.2017
11:20:41
Ага! А покажи, как класс ообъявляешь.

Pavel
16.10.2017
11:21:58
type MessagingManager<'C> ( cts: CancellationTokenSource,
raftRequestProcessor,
raftResponseProcessor,
config) as self =
...
let sender = MailboxProcessor<SenderCommand<'C>>.Start((fun inbox ->
...

Evgeniy
16.10.2017
11:23:29

Pavel
16.10.2017
11:23:54
вроде нет
я сейчас попробую отделить предметную область от этого класса, чтобы он не зависил от половины окружающего проекта, но странная ошибка =\

Evgeniy
16.10.2017
11:27:39
вроде нет
Странно. Я набросал небольшой пример.
http://bit.ly/2yrKYMd
Можно посмотреть в C# код, в конструкторе создается агент с генерик-параметром класса.

Pavel
16.10.2017
11:29:40
в том-то и дело, что в соседнем файле всё ок:
type RequestManager<'C>(cts: CancellationTokenSource,
config: RequestConfig,
requestSender,
responseProcessor,
receiver,
req: RequestData<'C>) =
let requestAgent = MailboxProcessor<SenderInfo * ResponseMessage>.Start((fun inbox ->

Roman
16.10.2017
11:31:26
Btw, просто если есть вопросы по провайдерам - пишите! Отвечу сначала здесь (может не сразу, аврально доделываю доклад), а потом и в докладе :)

Pavel
16.10.2017
11:40:57
разве код, расположенный далее должен перекрывать типы, указанные явно?

Google

Evgeniy
16.10.2017
11:48:57
Муть какая-то. Может студия тупит?

Pavel
16.10.2017
11:52:14
хотяя тут подсветка синтаксиса уже ломается

Evgeniy
16.10.2017
12:02:33
Если навести на 'C, то какое сообщение об ошибке?

Pavel
16.10.2017
12:03:21
This type parameter has been used in a way that constrains it to always be 'obj'

Evgeniy
16.10.2017
12:04:28
Скорее всего внутри агентов что-то ломает вывод типов. Можно попробовать расставить явные аннтоации типов, чтобы поймать ошибку.

Nikolay
16.10.2017
12:06:52
@gsomix помнишь такое было в Natty?

Evgeniy
16.10.2017
12:07:09
Неа.

Nikolay
16.10.2017
12:08:10
Pavel у тебя там не printf-like функция в аргументе?

Pavel
16.10.2017
12:09:12
в
type MessagingManager<'C> ( cts: CancellationTokenSource,
raftRequestProcessor,
raftResponseProcessor,
config) as self =
функция raftResponseProcessor имеет тип что-то -> unit

Nikolay
16.10.2017
12:09:25
Похоже в этом косяк, да
У меня есть такая функция в коде:
let sqlQueryf a = printfFormatProc sqlProcessor a
и выдавало такую же ошибку как у тебя, когда я пытался сделать так:
let sqlQueryf<'x> a = printfFormatProc sqlProcessor a
Ломается всё из-за такой конструкции:
PrintfFormat<'a, _, _, 'd>

Pavel
16.10.2017
12:12:05
ну у меня ничего рядом с printf нет, только сигнатура в юнит
т.е. проблема не в формате

Evgeniy
16.10.2017
12:12:23

Nikolay
16.10.2017
12:12:34
А RequestProcessor?
@gsomix ты не вспомнил? :)