Ayrat
https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1023-type-providers-generate-types-from-types.md
Ayrat
Вот сразу рфц
Romɑn
https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1023-type-providers-generate-types-from-types.md
Долистал, да. Это же восхитительно. А говорите ТП не нужны. Завтипы!
Doge
https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1023-type-providers-generate-types-from-types.md
Интересно, какие там типы в итоге допустимы в реализации
Vladislav
Да даже эти ебаные toJson fromJson можно туда впихать
Да эта хрень нормальным сертализатором решается. Но с ебанутыми может помочь да
Doge
Долистал, да. Это же восхитительно. А говорите ТП не нужны. Завтипы!
Ну это не зав типы. Для полноценных зав. типов тебе нужно иметь выражать зависимость типа не только от литералов, но и от значений любого типа
Romɑn
https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1023-type-providers-generate-types-from-types.md
Если туда ещё и ф-ции можно запихнуть будет, они же тоже типы, то это что вообще сделать, то можно!!
Doge
Я про возможности
Ну возможностей море, это да, хорошая штука. Хотя, конечно, тайп провайдеры не самая удобная штука в реализации и использовании.
Romɑn
Ну возможностей море, это да, хорошая штука. Хотя, конечно, тайп провайдеры не самая удобная штука в реализации и использовании.
Это если она завязана на какие-то внешние источники. Все легковесные, нарримердля парсинга жсонов, или регексы, у меня всегда отлично работали. Но если много чего надо учесть, а в сложных ТП учитывать надо дохрена, то конечно можно и говно написать.
Vladislav
Ну возможностей море, это да, хорошая штука. Хотя, конечно, тайп провайдеры не самая удобная штука в реализации и использовании.
Да если их так писать без внешнего мира то норм. Надо бы свой жсон провайдер написать по-человечески...
Vladislav
А то лежит недоделанный
Vladislav
По фичам
Shub
https://www.quora.com/Functional-Programming/Which-of-Haskell-and-OCaml-is-more-practical-For-example-in-which-aspect-will-each-play-a-key-role/answer/Jon-Harrop-2?share=1&srid=OsrX
Vasily
Наброс хорош
Vasily
Что нам ответит @DogeShibu ?
Андрей
F# Flood: клуб анонимных хаскельхейтеров
Doge
Что нам ответит @DogeShibu ?
Ну так, вбросовенько. Так что вброшу свой ответ: Окамл объективно не плох (разве что с многопоточным рантаймом там реально долгое время была проблема), да и система типов с полноценным модулями там веселая и позволяет кучу интересных хаков. Но у него есть хронический и фатальный для нашего времени недостаток: он нифига не моден и не хайпуется. О нем слышали с десяток человек, а реально писали два с половиной олдфага. Что приводит к тому, что в экосистеме не очень много новых людей, найти библиотеки под современную инфраструктуру там ещё сложнее, чем в хаскеле. Понятия оттуда не переходят в другие ЯП. (А хаскель уже проник тем или иным способом почти всюду) Что печально, потому что полноценные ML модули - это дикая сила. И да, имхо, главная трагедия F# в том, что этих модулей до него не довезли.
Doge
Что нам ответит @DogeShibu ?
Ну и да, как было выше сказано, я тайп астронавт в душе, поэтому мне сойдёт любой язык, где достаточно мощная система типов. Так что против ocaml'а ничего не имею. Был бы он получше распиарен и с чуть более живой экосистемой, то вполне вероятно, что я бы и на нём писал.
Vasily
Потом оказывается, как у Пелевина в Омон ра
Doge
Это то, что я не боюсь в реальных проектах юзать, как минимум.
Vasily
Оказывается, что космос есть только под веществами
Doge
как тайп астронавт мог бы иногда показывать, чего полезного в вашей астронавтике есть. а то вы все больше в стиле "в космос летал, но Бога не видел"
Т.е. из реальных примеров есть такая задачка: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=971e065e48b4afdc8dabf71db800540c На скале она у меня в приложении решается в 20 строк на shapeless, экономит кучу дублирования кода и ручной мороки.
Doge
На расте, увы, но похоже, что только процедурными макросами.
Doge
Извиняюсь за раст, но недавно как раз про неё спрашивал, когда хотел понять, может кто-то в расте до меня подобный макрос написал
Doge
как тайп астронавт мог бы иногда показывать, чего полезного в вашей астронавтике есть. а то вы все больше в стиле "в космос летал, но Бога не видел"
Из менее метапрограммичного, ещё дико радуют абстрактные типы в скале/associated типы в расте/type families в хаскеле. (Да, они разные по сути, но использовать можно в похожем ключе, кстати и с ML модулями так можно проектировать) Общая идея в том, что ты можешь к тайпклассу/трейту/интерфейсу прекрепить какой-то набор типов, которые будут определять те, кто его реализуют: Достаточно условный пример, но суть пояснит: trait Graph { type Node type Edge def createNode(id: Int): Node def createEdge(from: Node, weight: Double, to: Node): Edge def getDistance(source: Node, destination: Node): Double } final class MyGraph { type Node = Int type Edge = MyEdge ... } Надо обратить внимание ещё на то, что в скале эти типы могут зависеть от конкретного инстанса трейта и через них как раз можно эмулировать зависимые типы. На практике я такое использую, когда хочется либо скрыть какие-то внутренние типы от потребителей, либо когда имеет смылс ради оптимизации у конкретной реализации использовать другой тип.
Igor
Из менее метапрограммичного, ещё дико радуют абстрактные типы в скале/associated типы в расте/type families в хаскеле. (Да, они разные по сути, но использовать можно в похожем ключе, кстати и с ML модулями так можно проектировать) Общая идея в том, что ты можешь к тайпклассу/трейту/интерфейсу прекрепить какой-то набор типов, которые будут определять те, кто его реализуют: Достаточно условный пример, но суть пояснит: trait Graph { type Node type Edge def createNode(id: Int): Node def createEdge(from: Node, weight: Double, to: Node): Edge def getDistance(source: Node, destination: Node): Double } final class MyGraph { type Node = Int type Edge = MyEdge ... } Надо обратить внимание ещё на то, что в скале эти типы могут зависеть от конкретного инстанса трейта и через них как раз можно эмулировать зависимые типы. На практике я такое использую, когда хочется либо скрыть какие-то внутренние типы от потребителей, либо когда имеет смылс ради оптимизации у конкретной реализации использовать другой тип.
Звучит как ООП
Igor
Doge
Звучит как ООП
Ага, только как ты такое в ООП сделаешь?
Doge
В стандартных ОО языках
Igor
Интерфейсы и классы?
Doge
Интерфейсы и классы?
Могу этот же код на хаскеле или расте написать
Doge
На расте он вообще почти один в один будет выглядеть
Doge
На хаскеле чуть по другому (т.к. там ф-ии create... будут с эффектом)
Igor
На расте он вообще почти один в один будет выглядеть
Мне кстати тут скалист задвигал, что ass.types в дотти (порезали и они) станут эквиваленты дженерик параметрам
Doge
Мне кстати тут скалист задвигал, что ass.types в дотти (порезали и они) станут эквиваленты дженерик параметрам
Нет, они вроде всё ещё path dependent, порезали их наоборот в другом ключе, ты теперь type projection сделать не можешь.
Doge
Ты теперь не сможешь как раз обратиться к конкретному типу и достать его такой тип: type MyGraphEdge = MyGraph#Edge Вот так нельзя будет
Doge
А можно будет вот так: def createAndProcessGraph(graph: Graph)(node: graph.Node): Double
Vladislav
Из менее метапрограммичного, ещё дико радуют абстрактные типы в скале/associated типы в расте/type families в хаскеле. (Да, они разные по сути, но использовать можно в похожем ключе, кстати и с ML модулями так можно проектировать) Общая идея в том, что ты можешь к тайпклассу/трейту/интерфейсу прекрепить какой-то набор типов, которые будут определять те, кто его реализуют: Достаточно условный пример, но суть пояснит: trait Graph { type Node type Edge def createNode(id: Int): Node def createEdge(from: Node, weight: Double, to: Node): Edge def getDistance(source: Node, destination: Node): Double } final class MyGraph { type Node = Int type Edge = MyEdge ... } Надо обратить внимание ещё на то, что в скале эти типы могут зависеть от конкретного инстанса трейта и через них как раз можно эмулировать зависимые типы. На практике я такое использую, когда хочется либо скрыть какие-то внутренние типы от потребителей, либо когда имеет смылс ради оптимизации у конкретной реализации использовать другой тип.
Звучит как вложенные классы из дотнета
Doge
Мне кстати тут скалист задвигал, что ass.types в дотти (порезали и они) станут эквиваленты дженерик параметрам
Порезали в том ключе, что раньше через type projection можно было делать произвольные вычисления (в них кто-то SKI выразил, например), да и вроде они вообще unsound были. Но их использование можно заменить на match типы скорее всего, там где это нужно.
Doge
Звучит как вложенные классы из дотнета
Ну проблема с ними, что ты их в интерфейсе не обьявишь
Ayrat
Из менее метапрограммичного, ещё дико радуют абстрактные типы в скале/associated типы в расте/type families в хаскеле. (Да, они разные по сути, но использовать можно в похожем ключе, кстати и с ML модулями так можно проектировать) Общая идея в том, что ты можешь к тайпклассу/трейту/интерфейсу прекрепить какой-то набор типов, которые будут определять те, кто его реализуют: Достаточно условный пример, но суть пояснит: trait Graph { type Node type Edge def createNode(id: Int): Node def createEdge(from: Node, weight: Double, to: Node): Edge def getDistance(source: Node, destination: Node): Double } final class MyGraph { type Node = Int type Edge = MyEdge ... } Надо обратить внимание ещё на то, что в скале эти типы могут зависеть от конкретного инстанса трейта и через них как раз можно эмулировать зависимые типы. На практике я такое использую, когда хочется либо скрыть какие-то внутренние типы от потребителей, либо когда имеет смылс ради оптимизации у конкретной реализации использовать другой тип.
а в чём тут отличие от обычных дженериков? interface Graph<Node, Edge> { createNode: int -> Node createEdge: ... } class MyGraph: Graph<Int, MyEdge> { ... }
Doge
А тут для вызывающей стороны тип не известен
Ayrat
То что дженерики определяет вызывающая сторона.
в твоём примере ты тоже объявил их на вызывающей стороне
Ayrat
в классе MyGraph
Doge
в твоём примере ты тоже объявил их на вызывающей стороне
На реализующей стороне, а не вызывающей.
Ayrat
В данном случае MyGraph уже конкретная имплементация Graph
Ayrat
это уже считай что вызывающая сторона
Doge
в классе MyGraph
Т.е. при вызове методов у какого-то Graph, мне ничего про типы Node и Edge известно не будет.
Doge
И я не смогу тому Graph их задать, в отличие от дженерик параметров.
Ayrat
Но ты же их объявил явно, в чём бонус их не знать?
Doge
Т.е. если ты попробуешь написать метод, который принимает IGraph, то тебе обязательно в нём потребуется указать эти же дженерик параметры.
Ayrat
ты захардкодил Int
Ayrat
я нихуя не понял, напиши мне код который внезапно сломается на языке с дженериками
Ayrat
который внезапно не ломается здесь
Doge
я нихуя не понял, напиши мне код который внезапно сломается на языке с дженериками
Большая разница в том, что в случае с IGraph общие методы придется писать вот так и протаскивать повсюду дженерик параметры: def processNode[Node, Edge](igraph: IGraph[Node, Edge]): Double = ... Тут ты можешь их спрятать внутрь того же Graph: def processNode(graph: Graph): Double
Vladislav
Господа, а можете объяснить что такое аппликативный функтор? А то в книге прочитал и нихуя не понял
Ayrat
Но я же просил про языки с дженериками
Vladislav
Не
Ayrat
В том же фшарпе так писать не надо
Ayrat
Пока неясно решительно нихуя
Vladislav
Моих мозгов сейчас хватает чтобы только летсплеи фоном смотреть
Igor
https://youtu.be/o2G22AIhplU
Doge
Есть языки с тайп инфиренсом. В скале он херовый
Это не для тайп инференса, это для некой логики на уровне типов (если про хаскель/раст/type projection в скале, это не сэмулируешь просто дженериками), либо для сокрытия типов от потребителя (относительно эмулируется дженериками, но не очень удобно) Если говорить про скалу, то доступно тут ещё более веселая штука, через такое можно делать зав. типы: trait FromValue { type Out } def example(from: FromValue): from.Out = ??? val one = new FromValue { type Out = Int } val oneInt: Int = example(one) val two = new FromValue { type Out = String } val twoString: String = example(two)
Igor
Гляну
Перематывай сразу на последние минут 10
Vladislav
А ты понял что такое функтор?
Чото что мапает значение в контейнере
Vladislav
Vladislav
Мне сложно