F#

Aug. 19th, 2010 05:00 pm
109: (Default)
[personal profile] 109
начал изучать F# сегодня после обеда. похоже, что к концу дня уже и закончил. никакой дополнительной гибкости по сравнению с C# не наблюдается. взять tuples. ок, я могу сматчить первый элемент как (x, _), аналогично head в списке. а как мне сматчить остаток (e.g. tail)? или как итерировать по тупелу заранее неизвестного типа? или как динамически создать тупел, имея, скажем, список типов элементов? а ведь без перечисленного мной ничего осмысленно реляционного не написать. вот у них ничего не пошевелилось в душе, когда они хуярили эти конструкторы?

Tuple(T1)
Tuple(T1, T2)
Tuple(T1, T2, T3)
Tuple(T1, T2, T3, T4)
Tuple(T1, T2, T3, T4, T5)
Tuple(T1, T2, T3, T4, T5, T6)
Tuple(T1, T2, T3, T4, T5, T6, T7)
Tuple(T1, T2, T3, T4, T5, T6, T7, T8)


bonus: Action(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16)

видимо, Билл Гейтс сказал, что 16 параметров должно быть достаточно для любого метода.
Page 1 of 4 << [1] [2] [3] [4] >>

(no subject)

Date: 2010-08-20 01:19 am (UTC)
From: [identity profile] sasha-gil.livejournal.com
а как мне сматчить остаток (e.g. tail)?

Вроде паттерны типа first::second::_ (сосиска может быть произвольной длины) должны работать.

По поводу енумирирования по произвольной tuple - это тебе, наверно, захотелось compile-time вычислений ("метапрограммирования" в стиле C++-темплейтов?), такого в F# нет.

(no subject)

Date: 2010-08-20 05:47 am (UTC)
From: [identity profile] thedeemon.livejournal.com
> first::second::_

Это для списков, не для туплов.
109 хочет использовать туплы как гетерогенные списки, а это без выкрутасов не типизируется. Есть ли в F# достаточные выкрутасы - не в курсе.

(no subject)

Date: 2010-08-20 06:45 am (UTC)
From: [identity profile] metaclass.livejournal.com
Вы с Хаскелем, замудреными системами типов и тому подобным оккультизмом хорошо знакомы?
"Динамически создать tuple, имя список типов" - во первых, не tuple а его тип, во вторых, это уже метапрограммирование или программирование на типах, кому что нравится.

В статически типизированных языках, действительно, часто не хватает таких возможностей и кажется, что они бы были серебряной пулей. Но это все до первой попытки реализовать их самостоятельно - в итоге оказывается, что получается что-то похоже или на Template Haskell с его адским вуду, или на Common Lisp с скобочками и макросами. Это если встраивать метапрограммирование в язык таким образом, чтобы его хоть как-то можно было использовать, не сломав мозг.

Альтернатива этому делу - кодогенерация, которая тоже не панацея. К широкому использованию непригодна, т.к. код кодогенератора при хоть сколько нибудь нетривиальной задаче превращается в жуткий ад.

Я сейчас как раз на F# пишу кодогенератор для model-driven design, накушался всего этого по полной программе :)

(no subject)

Date: 2010-08-20 06:46 am (UTC)
From: [identity profile] metaclass.livejournal.com
Отправить его читать Олега про HList и возрадоваться очередной душе, попавшей в цепкие лапы инфернального ФП :)

(no subject)

Date: 2010-08-20 06:51 am (UTC)
From: [identity profile] metaclass.livejournal.com
А насчет гибкости F# - у меня пока на F# код получается сильно проще и читабельнее, чем аналогичный на C#, благодаря ADT, композиции функций, частичному применению функции, синтаксису с отступами и иммутабельности. Основная фича, которая делает F# гораздо более перспективнее других функциональных языков - интеграция с C# и прочим дотнетом, т.к. в других языках интеграция с внешним миром - исключительно через зад, то бишь чистый C, ручной маршалинг типов, указатели на указатели на указатели и прочий трэш.

(no subject)

Date: 2010-08-20 07:17 am (UTC)
From: [identity profile] 109.livejournal.com
> "Динамически создать tuple, имея список типов" - во первых, не tuple а его тип

и тип, и сам кортеж. у меня есть метаданные, например [int; string; DateTime], а теперь мне надо создать инстанс и вставить в таблицу, ну или другую коллекцию по моему усмотрению.

всё это уже делалось разными фреймворками много раз, но за отсутствием языковой поддержки всегда выходило коряво. а тут, казалось бы, наконец можно сделать хорошо, ан нет, получилось как всегда.

(no subject)

Date: 2010-08-20 07:20 am (UTC)
From: [identity profile] metaclass.livejournal.com
вот, языковая поддержка:
> open System;;
> let tupleInstance = (1,"zhopej",DateTime.Now);;

val tupleInstance : int * string * DateTime =
(1, "zhopej", 20.08.2010 10:20:30)

(no subject)

Date: 2010-08-20 07:32 am (UTC)
From: [identity profile] 109.livejournal.com
у меня создалось впечатление, что пока код можно писать в рамках tuples, lists, sequences, dict и прочих родных структур, то да. но шаг вправо или влево - расстрел.

(no subject)

Date: 2010-08-20 07:33 am (UTC)
From: [identity profile] 109.livejournal.com
ну напиши мне функцию, которая принимает i и возвращает i-й по счёту элемент кортежа.

ну то есть если мы говорим, что F#-ские кортежи хороши для представления датабазных кортежей, то я прошу написать мне SqlDataReader.GetValue(i)

> тебе, наверно, захотелось compile-time вычислений

нет, мне как раз в рантайме надо это делать.

(no subject)

Date: 2010-08-20 07:36 am (UTC)
From: [identity profile] 109.livejournal.com
> 109 хочет использовать туплы как гетерогенные списки

нет. мне нужна удобная языковая поддержка датабазных кортежей. а туплами их назовут, или хрюплами, пофиг. собственно, самим словом tuple их так позиционировали, но использовать их для этой цели, как выяснилось, невозможно.

(no subject)

Date: 2010-08-20 07:39 am (UTC)
From: [identity profile] metaclass.livejournal.com
Еще там есть ADT, записи ну и классы с интерфейсами, как положено.

А что еще нужно, все остальное из этого комбинируется.

(no subject)

Date: 2010-08-20 07:47 am (UTC)
From: [identity profile] metaclass.livejournal.com
Нет, это как раз compile-time вычисления, т.к. подобная функция стандартными средствами не типизируется.
Собственно говоря, нет проблемы сделать это через Reflection, но это же натягивание совы на глобус и добровольный отказ от преимуществ статической типизации.
SqlDataReader.GetValue(i) и прочий ADO.NET, JDBC, итд - это динамическая типизация.

Чтобы одновременно было и это и статическая типизация - нужна очень хитрая система типов, с инкрементальной типизацией. Она все равно валится будет в рунтайме, если будут ошибки типов, т.е. гарантии валидности будут более слабые, но в отличие от теперешней чисто динамической типизации - валится будет раньше, на этапе prepare запроса (или еще раньше, при подключении к БД), а не на этапе выполнения с обращением к кривому типу и то если результат запроса не пустой.

(no subject)

Date: 2010-08-20 07:47 am (UTC)
From: [identity profile] 109.livejournal.com
я уверен, что ты понимаешь, что я имею в виду, только прикидываешься. у меня нет никаких "zhopej", когда я код пишу. да и у тебя нет. а есть row metadata в виде, например, Type list.

и GetValue(i) напиши тоже заодно (см. выше), чтобы два раза не вставать.

(no subject)

Date: 2010-08-20 07:54 am (UTC)
From: [identity profile] 109.livejournal.com
перевожу на русский язык: F# не может сделать того, что дельфи могла ещё в прошлом веке, и концепция кортежа (tuple), сделанная в F# first-class citizen, имеет мало отношения к кортежам баз данных, по большому счёту бесполезна, и введена из чисто маркетинговых соображений.

(no subject)

Date: 2010-08-20 07:59 am (UTC)
From: [identity profile] 109.livejournal.com
и ты даже пример (zhopej) привёл, чтобы показать, как это мощно и удобно!

(no subject)

Date: 2010-08-20 08:00 am (UTC)
From: [identity profile] metaclass.livejournal.com
про GetValue я уже написал там
Type list - это то же самое, закат солнца вручную - реализация динамической типизации руками поверх языка со статической типизацией.
Во всех попадавшихся мне под руку языках интеграция этого в статическую типизацию или невозможна, или реализуется через метапрограммирование на макросах, или через инфернальный type-level programming типа того же HList. А i там приходится выражать в нумералах чёрча, ага.
Еще один вариант - Reflection

И кстати, насчет GetValue(i) - предлагаю сразу задуматься, какие применения для него? Я пока вижу только как адаптер к нетипизированным вещам вроде DataGrid или типа "вывести тупл целиком в строку".

(no subject)

Date: 2010-08-20 08:09 am (UTC)
From: [identity profile] metaclass.livejournal.com
Еще раз: не нужно путать статическую и динамическую типизации.
Дельфи(TDataset, bde и dbexpress и прочая), ADO, ADO.NET, и 90% других базоданновых либ - это все динамическая типизация.
F# tuples, C# class и struct, записи, ADT и прочее - это статическая типизация, со своей достаточно строгой теорией. Tuples в F# введены, т.к. это очевидный элемент оной теории.
Интеграция этого дела возможна, но тянет за собой множество заморочек, которые отражаются в крайней невменяемости большинства ORM-либ. Оные ORM как раз и решают задачу "адаптировать систему типов БД и систему типов языка". Прозрачной интеграции я пока не видел вообще нигде и ни разу, т.к. языки у которых есть нужные для этого фичи, либо сами по себе динамически типизированы, либо в продакшене не используются/


Я лично tuple использую массово чтобы не создавать руками новые типы данных, если мне нужно вернуть два-три значения в результате функции. Если больше - то лучше использовать записи, то бишь те же самые туплы, но вместо порядка полей в них поля именованные.

(no subject)

Date: 2010-08-20 08:19 am (UTC)
From: [identity profile] 109.livejournal.com
> И кстати, насчет GetValue(i) - предлагаю сразу задуматься, какие применения для него?

эээ... вообще-то через него, или его аналог, работает вообще всё что database-related, включая "типизированные" датасеты, таблицы, whatever.

в свою очередь, предлагаю задуматься над причиной появления инфернального HList. значит, есть таки потребность? ну и заодно, что лучше, иметь tuples, которые не tuples, и сбоку прикрученные классы, которые на самом деле позволяют с данными работать, или реализовать один раз нормально?

я не вижу, почему так принципиально трудно сделать нормальную языковую поддержку для операции, например, [int; string] -> int * string - при том что, как ты сам правильно заметил, сделать это через reflection не представляет проблем (unless число элементов в списке типов больше восьми ;).

всё, я пошел спать, глаза слипаются.

(no subject)

Date: 2010-08-20 08:36 am (UTC)
From: [identity profile] metaclass.livejournal.com
[typeof(int);typeof(string)] -> int*string?

Теоретически трудно сделать, да. Т.к это означает все те же compile-time вычисления.

(no subject)

Date: 2010-08-20 08:48 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Функция создания инстанса будет возвращать нечто, тип чего при компиляции неизвестен, т.к. определяется содержимым входного списка. Т.е. в рамках обычной статической типизации (а в F# она) это невозможно. Возможно в динамической (привет тонны тестов) и в зависимой (привет катаморфизмы, эндофункторы и санитары).

(no subject)

Date: 2010-08-20 08:53 am (UTC)
From: [identity profile] volodymir-k.livejournal.com
ОК, реальный пример. Программа должна:
* спрашивать у юзера коннект к БД, таблицу, логиниться
* показать список полей
* показать первых 30 строк таблицы.
Юзер может ввести БД и таблицу, какие угодно (созданные после компиляции программы).

Ява, Бейсик, паскакаль, писон -- без проблем. Ф#?

(no subject)

Date: 2010-08-20 09:04 am (UTC)
From: [identity profile] metaclass.livejournal.com
Точно так же как в C# - ADO.NET, отражение информации о типах в рунтайме в виде данных(динамическая типизация) и вперед.

Статическая система типов F# в данном случае не поможет ничем и никак.

Хотя у меня есть идея реализовать именно для этого use case собственный фреймворк с инкрементальной типизацией и кодогенерацией-компиляцией в рунтайме. Пока отложено в долгий ящик, т.к. решение задачи требует сначала реализовать то же самое в более простом варианте, с предварительной кодогенерацией.
Ну и единственное место в продакшене где у меня динамическая и статическая типизации пересекаются - это когда из такого грида нужно отобразить написанный руками конкретно под данную таблицу редактор или выполнить какой-нибудь расчет, тоже исходя из данных таблицы. Приходится заниматься приведениями типов, обращениями по имени к полям, итд :)

(no subject)

Date: 2010-08-20 09:33 am (UTC)
From: [identity profile] 184467440737095.livejournal.com
есть у вас Tuple(T1, T2): (a, b)
вы хотите функцию, (T1, T2)->int -> ??? : f, такую что f(a,b)(1) = T1:a, f(a,b)(2) = T2:b
подозреваю что проверить при компиляции отсутствие ошибок типизации в выражении, содержащем такую функцию, нельзя, поэтому есть две отдельных функции (T1,T2)->T1: f(1) и (T1,T2)->T2: f(2), .Item1 и .Item2 соответвенно.

поскольку в момент компиляции метаданные отношения, для которого нужно создавать кортежи, вам не известны, то в любом случае с туплами или без них, придется динамически по описанию тупла генерить его тип и потом сами туплы.

(no subject)

Date: 2010-08-20 09:35 am (UTC)
From: [identity profile] zamotivator.livejournal.com
я не вижу, почему так принципиально трудно сделать нормальную языковую поддержку для операции, например, [int; string] -> int * string - при том что, как ты сам правильно заметил, сделать это через reflection не представляет проблем (unless число элементов в списке типов больше восьми ;)..
Список имеет тип List A = A * List A | EmptyList.

Список это элемент типа A и ещё точно также список, либо пустой список.
Другими словами, списки гомогенны (содержат элементы одинакового типа данных).

Если же у нас списки гетерогенные - начинается веселуха.

В терминах ООП у нас вводится базовый класс Base и два наследника - A и B
И мы получается список Base'ов... А не список A, B.

В терминах ФЯП это описывается как:
Base = A | B
List Base = Base * List Base | EmptyList;

Теперь приходим к понимаю, что для списка длиной два есть четыре варианта:
A, A
A, B
B, A
B, B

Ну и как это говно типизировать?
Вот и появлются tuple.

Tuple 'a 'b = a' * 'b;
get (a,b) i = match i with
0 -> a
1 -> b
end;

Какой тип результата get?
Естественно, a | b

Теперь проблема понятна?

(no subject)

Date: 2010-08-20 09:39 am (UTC)
From: [identity profile] 184467440737095.livejournal.com
тупл это
1) функция, превращающая несколько значений в значение декартового произведения типов
2) функция проекции этого произведения обратно в компоненты

что и написано в документации по приведенной вами ссылке
собственно, самим словом tuple их так позиционировали.


Page 1 of 4 << [1] [2] [3] [4] >>

Profile

109: (Default)
109

March 2019

S M T W T F S
     12
3456789
101112131415 16
17181920212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags