Previous Entry Share Next Entry
2016-01

Зачем нужны динамические языки?

http://gnuu.org/2010/12/13/too-lazy-to-type/

>> Are we really writing "dynamic" programs, or are we just trying to avoid writing down all those type signatures?

Да, естественно. Сделает кто-то язык, у которого не будет monomorphism restriction и будут выводиться sum types и rank2 types (а остальное будет писать ворнинги и работать в динамике) - его ж на руках носить будут.

Профит от динамики в том, что не нужно прогибать мозг (в начале разработки) под расхождения системы типов и проблемной области (в счет последующих багфиксов, но начальству-то уже показано, что работает, а к багам все привыкли)

Причем, уже ж вполне наработаны и обкатаны технологии gradual typing – на тех же Javascript-движках, которые продолжают делать вид, что язык динамический %)

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

Тем временем, пока такую штуку еще не сделали, буду писать на Питоне дальше :D

за наводку спасибо thesz


  • 1
thedeemon December 17th, 2010
>язык, у которого не будет monomorphism restriction и будут выводиться sum types и rank2 types

А можно примеров того, как это бы выглядело/использовалось?


wizzard0 December 17th, 2010
ну, убрать MR - имхо проблема чисто стилистическая.

вывод sum types практически избавляет нас от необходимости писать data declarations и дает (имхо) даже более мощный инструмент, чем polymorphic variants из камла.

вывод rank2 вкупе с отсутствием MR дает возможность писать намного меньше type definitions для функций высшего порядка и то самое "не нужно прогибать мозг (в начале разработки)"

Также, не исключено что я где-то гоню (например, перепутал термины с похожими именами)

thedeemon December 17th, 2010
А в чем разница между polymorphic variants из камла и выводом sum types?

Реквестирую пример жизненной ФВП, которая требует описания типов и прогибания мозга.

wizzard0 December 17th, 2010
хм, жизненная ФВП...

ну вот в текущем проекте есть factory парсеров, парсящих arbitrary data structures (в смысле, не только списки строк\токенов), это вполне себе ФВП rank2, может и больше. как ее протипизировать - я откровенно не представляю.

thedeemon December 17th, 2010
А у фабрики внутри что-то обобщенное или просто для разных типов аргумента разные функции на выходе?
В первом случае часто достаточно обычного полиморфизма, даже не rank2.
Во втором напрашиваются sum types с перечислением вариантов.

wizzard0 December 17th, 2010
У фабрики внутри, э, parser generator. Питается грамматиками. При желании их можно переписать в виде каких-нибудь quotations, а пока что они в банальном текстовом файле, в котором и паттерны (на своем языке), и rule callbacks (на питоне)

thedeemon December 17th, 2010
Вроде, можно обойтись без высоких рангов.

type ('token, 'res) rule = R1 of 'token * 'res option | R2 of 'token * 'res option (*kinds of rules*)
type ('token, 'res) grammar = ('token, 'res) rule list
type ('token, 'res) parser = 'token list -> 'res option
type ('token, 'res) factory = ('token, 'res) grammar -> ('token, 'res) parser

wizzard0 December 17th, 2010
Думаю.

(думал 15 минут, в итоге всё стёр)
Без высоких рангов обойтись, конечно, можно. Только типизация какая-то динамическая получается.

Т.е. вот сейчас есть (извращенная, без BinOp можно тривиально обойтись, но хочется проиллюстрировать) грамматика для калькулятора.

grammar Calc{
Number = Number:n Digit:d -> n*10 + int(d)
| Digit:d ' '* -> int(d)

BinOp :arg1 :opChar :arg2 :op = arg1:x opChar arg2:y -> op(x,y)

UnaryExpr = Number | '(' AddExpr ')'
MulExpr = BinOp(MulExpr, '*', UnaryExpr, lambda a,b: a*b):x -> x
| PrimExpr:x -> x
AddExpr = BinOp(AddExpr, '+', MulExpr, lambda a,b: a+b):x -> x
| MulExpr:x -> x

Start = AddExpr
}

У грамматики 'res, очевидно, int. 'token - char.
А у правил?

P.S. надеюсь, нигде не опечатался :D

thedeemon December 18th, 2010
У правил типы результатов могут быть разными, тогда в схеме выше будет побольше параметров, но суть не изменится.

wizzard0 December 17th, 2010
Под выводом sum types я подразумеваю возможность пособирать все конструкторы типа по программе и закрыть его, чтобы можно было проверить, total или не total у нас функции. В polymorphic variants, вроде, это невозможно (поправь(те)), если можно.

thedeemon December 17th, 2010
А как узнать, относится ли некий конструктор к этому же типу, без описания типа? Какова процедура "закрытия"?

wizzard0 December 17th, 2010
Из dataflow?

thedeemon December 17th, 2010
Это есть:
let is_fruit = function 
  | `Orange | `Apple -> true 
  | `Fish | `Truck _ -> false
	
let make_food = function
  | 1 -> `Orange | 2 -> `Fish | _ -> `Carrot

let x = is_fruit (make_food 3);;
------------------^^^^^^^^^^^-------
Error: This expression has type [> `Carrot | `Fish | `Orange ]
but is here used with type [< `Apple | `Fish | `Orange | `Truck of 'a ]
The second variant type does not allow tag(s) `Carrot

wizzard0 December 17th, 2010
Любопытно. Из доков не совсем очевидно, что это так работает (я на камле мало писал). Тогда разница получается тоже чисто в синтаксисе (=> почему бы и не реализовать)

thedeemon December 18th, 2010
Не понял последнюю фразу (с чем разница и где реализовать).

jtootf December 17th, 2010
будут выводиться...rank2 types

а это разве возможно?

wizzard0 December 17th, 2010
В общем случае вроде нельзя. Я про что-то вроде http://research.microsoft.com/en-us/um/people/simonpj/papers/boxy/boxy-icfp.pdf (хотя понимаю я пейпер плохо, честно говоря)

3d6 December 17th, 2010
Мда, мне все это абсолютно непонятно, но когда у меня возникает проблема обработки данных неизвестного заранее типа - я в С++ использую такую штуку как тип void, а на месте уже смотрю, что там внутри этого воида, и обрабатываю соответственно :)

0bs3rv3r December 18th, 2010
Приз зрительских симпатий отхожит этому камениту.

  • 1
?

Log in

No account? Create an account