metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2012-02-24 10:44 am

Типы и типы

Очевидно ли, почему flatten и (partial apply concat) в Clojure могут выдать разные результаты? После хаскеля кложурный flatten, работающий на все уровни "вглубь", выглядит непривычно.

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

[identity profile] cp-poster.livejournal.com 2012-02-24 08:14 am (UTC)(link)
> По ходу, статическая типизация делает невозможными некоторые типы программ, возможные при динамической.
Это тянет на теорему. Какие например типы?

[identity profile] thesz.livejournal.com 2012-02-24 08:29 am (UTC)(link)
Вот именно.

И к заявлениям [livejournal.com profile] metaclass: зависимые типы делают большее количество программ допустимыми.

[identity profile] metaclass.livejournal.com 2012-02-24 08:36 am (UTC)(link)
Мы тут с [livejournal.com profile] theiced на эту тему спорили. Он привел пример вроде

charAt s i = s.[i]

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

[identity profile] thesz.livejournal.com 2012-02-24 09:05 am (UTC)(link)
Это же на Хаскеле даже можно сделать.

Кстати, пример с корректной адресацией элементов массива идёт не то первым, не то вторым примером в какой-то из статей про Эпиграм. Вот трансляция оттуда в Хаскель по памяти:
{-# LANGUAGE GADTs #-}

data Zero = Zero
data Succ n = Succ n

data Vec len a where
	Nil :: Vec Zero a
	Con :: a -> Vec len a -> Vec (Succ len) a

data NatUp up where
	Z :: NatUp (Succ len)
	S :: NatUp len -> NatUp (Succ len)

charAt :: Vec len Char -> NatUp len -> Char
charAt (Con c _) Z = c
charAt (Con _ v) (S n) = charAt v n

good = charAt (Con 'a' Nil) Z
--bad = charAt (Con 'a' Nil) (S Z) -- не пройдёт!!!

[identity profile] metaclass.livejournal.com 2012-02-24 09:18 am (UTC)(link)
О.
Т.е. если мы вводим s пользователем, то полный тип программы выведется только после ввода строки, или не выведется, потому что пользователь ввел "a" а мы обращаемся ко второму символу.
Соответственно, вместо обработки исключений в рантайме у нас вывод типов в рантайме, причем нужно еще куда-то сунуть локализуемое сообщение об ошибке, чтобы его показать пользователю.

Это можно сделать на зависимых типах?

[identity profile] thesz.livejournal.com 2012-02-24 09:31 am (UTC)(link)
>Т.е. если мы вводим s пользователем, то полный тип программы выведется только после ввода строки, или не выведется, потому что пользователь ввел "a" а мы обращаемся ко второму символу.

Нет.

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

Гарантии указаны в типе. Контракте, если изволите.

Нарушение контракта можно переводить в сообщение об ошибке.

[identity profile] metaclass.livejournal.com 2012-02-24 09:40 am (UTC)(link)
А, пользователю просто нельзя дать ввести строку, короче, чем мы к ней обращаемся. Мы ее просто никак не скастуем к допустимому для системы типу.

[identity profile] thesz.livejournal.com 2012-02-24 09:50 am (UTC)(link)
Именно так.

[identity profile] si14.livejournal.com 2012-02-24 10:06 am (UTC)(link)
Посмотрите http://www.bluishcoder.co.nz/2010/09/01/dependent-types-in-ats.html , там достаточно пространно объясняется, что такое зависимые типы и что на них можно сделать.

[identity profile] zmila.livejournal.com 2012-02-24 01:56 pm (UTC)(link)
а в pascal

type
  my_range = 1 .. 21;
  my_string = array [my_range] of char;
var
  my_i : my_range;
  my_s : my_string;


не то?

[identity profile] thedeemon.livejournal.com 2012-02-24 03:55 pm (UTC)(link)
Я показывал примеры, как на языке с упрощенными зависимыми типами это легко делается
http://thedeemon.livejournal.com/41035.html

[identity profile] metaclass.livejournal.com 2012-02-24 08:34 am (UTC)(link)
Тут в комментариях поправили: сделать то же самое на статике можно, но в те места, где я сейчас передаю просто хеш-мап-словарь-объект с несколькими вариациями полей, придется засовывать либо алгебраический тип с возможными вариантами, если их конечное количество, либо экзистенциалы, с тайпклассами типа "меня можно использовать как параметры запроса" и "меня можно сохранить в json"

А когда дело доходит до того, что кроме json нужно отдать еще и html/xml/csv как положено RESTful сервису, сигнатуры типов начинают рыдать кровавыми слезами.

[identity profile] thesz.livejournal.com 2012-02-24 09:32 am (UTC)(link)
В Хаскеле и многих других ЯП есть строго типизированный Dynamic.

И типы в порядке, и динамичность есть.

[identity profile] thedeemon.livejournal.com 2012-02-24 03:52 pm (UTC)(link)
В ОО-языках это делают интерфейсами, значит в хаскелях делается тайпклассами, навороченные АДТ тут не нужны.