LINUX.ORG.RU
Ответ на: комментарий от AndreyKl

ты можешь хоть на ассемблере выразить сум тайп

почему бы не выразить это сигналами транзисторов в процессоре, lol. Эта мантра довольно-таки забавна, интересно откуда она взялась? Реализация не эквивалентна выражению. Выражение предполагает, что кто-то может это без усилий воспринимать(e.g. читать код и без усилий понимать его), это языковое свойство, а язык — это средство общения человека с машиной, некий интерфейс.

anonymous ()
Ответ на: комментарий от anonymous

не определена категория типов? :-)

Не определена значит не существует? Высокоуровневые языки разве не для того существуют, чтобы определять и строить абстракции?

anonymous ()
Ответ на: комментарий от anonymous

Не определена значит не существует?

Вполне возможно.

Высокоуровневые языки разве не для того существуют, чтобы определять и строить абстракции?

«Дорога, по обеим сторонам которой тянутся канавы, называется шоссе. Канава — это выкопанное значительным числом рабочих углубление. Копают канавы при помощи кирок.
Книга это множество нарезанных в четвертку листов бумаги разного формата, напечатанных и собранных вместе, переплетенных и склеенных клейстером. Клейстер — это клей.»

anonymous ()
Ответ на: комментарий от AndreyKl

Куда интереснее списки, например.

[a] = 1 + a + a^2 + a^3 + ... = 1 / (1 - a), откуда
[a] * (1 - a) = 1, откуда
[a] = 1 + a * [a]

Ну или более коротким путём:

[a] = 1 + a + a^2 + ... = 1 + a * (1 + a + a^2 + ...) = 1 + a * [a]

Такими манипуляциями можно получить пару альтернативных определений списка:

[a] = (1 + a) + a^2 * (1 + a) + a^4 * (1 + a) + ... = (1 + a) * (1 + a^2 + a^4 + ...) = (1 + a) * [a^2]
[a] = 1 + a * [a] = 1 + a * (1 + a) * [a^2]

Или в хаскеле:

data List a = List (Maybe a) (List (a, a))
data List a = Nil | List a (Maybe a) (List (a, a))

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

nezamudich ★★ ()
Ответ на: комментарий от utf8nowhere

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

 b ^ [a] = b ^ (1 + a * [a]) = b * (b ^ [a]) ^ a 

То есть тип [a] -> b изоморфен типу:

data T a b = T b (a -> T a b)

Тут есть над чем покурить.

nezamudich ★★ ()
Ответ на: комментарий от AndreyKl

паттерн матчинг, без которого как без рук просто

какой нахрен паттерн-матчинг в хаскеле? В виде синтаксической косметики над ветвлением? Какой толк в этом кроме экономии на спичках? Шоб було?

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

anonymous ()
Ответ на: комментарий от anonymous

Это не ортоганално. Эти инструменты родились как взаимодополнение друг другу, это основные механизмы декларативных ЯП. К хаскелю же, и прочим ФЯ паттерн-матчинг просто притянут за уши.

anonymous ()
Ответ на: комментарий от anonymous

Да и невозможен паттерн-матчинг без бектрекинга. Для доказательства «есть такое A что... » в случае неудачи нужно произвести откат и продолжить вычисление.

anonymous ()
Ответ на: комментарий от anonymous

Но есть каноническое определение паттерн-матчинга в CS. Истоки идут приблизительно отсюда

http://papers.cumincad.org/data/works/att/a162.content.pdf

Этой теме, в частности, посвящена отдельная глава в SICP — курсе введения в CS в MIT. Это классика.

Называть то можно что угодно чем угодно, суть от этого не меняется

anonymous ()
Ответ на: комментарий от anonymous

Шоб було?

Для конструкции и деконструкции данных. Без этого Хаскел немыслим. А в эрланге эт вообще суть философия. Падаем при сфейлишемся ПМ и рестартуем. Код писать легко, нет нужды в контроле состояния. При этом эрланг язык без бэктрейсинга

anonymous ()
Ответ на: комментарий от anonymous

Хорошо когда может быть выражена(в тч синтаксически). Когда встроена — не всегда хорошо.

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

anonymous ()
Ответ на: комментарий от nezamudich

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

anonymous ()
Ответ на: комментарий от nezamudich

Тут есть над чем покурить.

Если честно, то я ничего особого не вижу.

Всё, что ты сделал, это показал, что функцию [a] -> b можно представить как пару функций (() -> b, a * [a] -> b) и вторую компоненту каррировать: a * [a] -> b ≅ a -> [a] -> b.

utf8nowhere ()
Ответ на: комментарий от nezamudich

Вот и новые подробности. Оказывается, паттерн-матчинг - это не плюшка, а единственный вариант доступа к меченым объединениям и записям? Тогда я уже не могу отнести его к плюсам.

den73 ★★★★ ()
Ответ на: комментарий от anonymous

ну, хотел бы я поглядеть как в языке без «встроенных» АТД (вроде си) реализовать проверку выхода за диапазон такую чтоб было видно мощь, так сказать.

AndreyKl ★★★★ ()
Ответ на: комментарий от den73

гм.

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

даже в си если ты будешь писать функции доступа, ты будешь вынужден делать этакое сопоставление с образцом (if(item.type == TYPE_ONE)) и никуда от этого не деться. Похоже что это в принципе единственный доступ к типу-сумме.

AndreyKl ★★★★ ()
Ответ на: комментарий от AndreyKl

Как ты предлагаешь обращаться к типу-сумме без сопоставления?

Здесь я определил тип Апельсин-или-яблоко-с-меткой. Пусть у нас переменная Ая имеет такой тип и компилятор про это знает. Вот как это выглядит в реальном лиспа (сокращая до Аиясм).

;; эти две функции и сеттеры для них можно нагенеририровать автоматически
;; и их не будет видно в исходном коде, будет только 
;; (Определить-меченное-объединение Аиясм Апельсин Яблоко)
(defun Аиясм-Яблоко (Сие)
  (assert (eq (Аиясм-Метка Сие) 'Яблоко))
  (the Яблоко (Аиясм-Значение Сие)))

(defun Аиясм-Апельсин (Сие)
  (assert (eq (Аиясм-Метка Сие) 'Апельсин))
  (the Апельсин (Аиясм-Значение Сие)))

;; А это собственно пример разбора 
(defun Превратить-в-число (Ая)
  (declare (type Аиясм Ая)
  (ecase (Аиясм-Метка Ая)
    (Яблоко
     (Вес (Аиясм-Яблоко Ая)))
    (Апельсин
     (Цена (Аиясм-Апельсин Ая))))

Здесь проверка идёт в рантайме и ecase - плохая конструкция, т.к. она не понимает, что речь идёт именно о тегах типа Аиясм, но это можно поменять, сделав специфическую конструкцию, она будет вполне органично смотреться. Избавиться от проверок в рантайме нельзя (т.е. я не знаю как), и тут как раз и есть профит Хаскеля - давай не будем тратить время на этот аспект.

Если перейти к лирике, я пробовал несколько либ паттерн-матчинга для лиспа. Но как-то ни одна не прижилась у меня. Отсюда вывод: для лиспа паттерн-матчинг - лишь инструмент, без него вполне можно обойтись.

Тебе ответная задача: напиши сравнение двух Аиясм на Хаскеле с ПМ, чтобы выдавалась какая-то инфа о месте, где они не совпадают.

den73 ★★★★ ()
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от den73

паттерн-матчинг это не плюшка и не калач, а банальное отражение того факта, что c^(a + b) = c^a * c^b, т.е. (a+b) -> c ≅ (a -> c, b -> c), т.е. способ записать функцию из sum type как несколько функций по каждому типу из суммы.

utf8nowhere ()
Ответ на: комментарий от den73

Честно говоря не помню лисп вообще. Попытался понять твой код, возник вопрос, подскажи пожалуйста: что то мешает написать

(defun Превратить-в-число (Ая)
  (declare (type Аиясм Ая)
  (ecase (Аиясм-Метка Ая)
    (Апельсин
     (Цена (Аиясм-Апельсин Ая))))


т.е. «забыть» одну из веток?

AndreyKl ★★★★ ()
Ответ на: комментарий от den73

Тебе ответная задача: напиши сравнение двух Аиясм на Хаскеле с ПМ, чтобы выдавалась какая-то инфа о месте, где они не совпадают.

Пытаюсь понять задачу. т.е. есть аясм1 и аясм2. И мы хотим сделать

если (аясм1==аясм2)
 сказать "они равны" 
иначе
 (сказать 
   "первый был яблоко, а второй апельсин" 
  или
   "оба яблоки но вес первого 100г а второго 200г"
  в зависимости от ситуации)
. Верно?

AndreyKl ★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от utf8nowhere

но ПМ ведь можно использовать и в выражениях (let,where,case), он не ограничен твоим применением

короче ПМ это удобный способ деконструкции и сравнения данных, мне непонятно чего ТС агрится. он представлен не только в Хаскеле. я бы однозначно выбрал язык с его поддержкой. например в Эрланге благодаря нему удобно разбирать бинарные протоколы http://erlang.org/doc/programming_examples/bit_syntax.html

доступ к полям в сишке это прошлый век, банально неудобно

anonymous ()
Ответ на: комментарий от anonymous

но ПМ ведь можно использовать и в выражениях (let,where,case), он не ограничен твоим применением

let bindings и прочее тобой перечисленное это сахар над лямбдами, а значит он попадает под «моё применение».

в Эрланге благодаря нему удобно разбирать бинарные протоколы

Это не тот ПМ, который Haskell или ML. Это просто встроенный в язык способ описания бинарных данных.

utf8nowhere ()
Ответ на: комментарий от den73

в общем не уверен верно ли понял задачу, но если верно, то вот, самый «обычный» способ

module Ao where

data Ao = Apple Int | Orange Int

difference :: Ao -> Ao -> String
difference (Apple a)  (Apple b)  | a == b    = "both are apples, weights are equal"
difference (Apple _)  (Apple _)  | otherwise = "both are apples, but weights are different"
difference (Orange a) (Orange b) | a == b    = "both are oranges, weights are equal"
difference (Orange _) (Orange _) | otherwise = "both are oranges, but weights are different"
difference (Apple _) _                       = "first is apple, second is orange"
difference _ _                               = "first is orange, second is apple"

AndreyKl ★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от AndreyKl

Ничего не мешает. Это недостаток, я об этом написал. Если хотим добавить поддержку, можно ввести конструкцию, к-рая будет писаться как-то так:

(Просеять-все-теги-меченого-объединения Ая Аиясм
  (Апельсин ; внутри этих скобок будет определно (Апельсин Ая)
   (Цена (Апельсин Ая))
  (Яблоко
   (Вес (Яблоко Ая)))
При этом компилятор обругается на упущение какого-то тега (а кстати, это нужно не во всех случаях) и не позволит обратиться к яблоку внутри ветки апельсина и наоборот.

den73 ★★★★ ()
Ответ на: комментарий от AndreyKl

А ведь весь смысл паттерн-матчинга(в изначальном, академическом смысле этого слова, именно в том, чтобы не описывать все случаи явным образом). В хаскеле паттерн-матчинг — это наоборот, получается, инверсия паттерн-матчинга. То есть, то что делает инерпретатор в декларативном языке, хаскелист делает вручную, и называет это «паттерн-матчингом».

anonymous ()
Ответ на: комментарий от den73

ну или так

data Fruit = Apple | Orange deriving (Show, Eq)
data Ao    = Ao Fruit Int

wdiff w1          w2         | w1 == w2  = "weights are equal"
                             | otherwise = "weights are different"

diff2 (Ao f1 a1)  (Ao f2 a2) | f1 == f2  = "both are of type " ++ show f1 ++ ", " ++ wdiff a1 a2
                             | otherwise = "first is " ++ show f1 ++ ", second is " ++ show f2

AndreyKl ★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от tailgunner

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

anonymous ()
Ответ на: комментарий от anonymous

какой нахрен паттерн-матчинг в хаскеле? В виде синтаксической косметики над ветвлением? Какой толк в этом кроме экономии на спичках? Шоб було?

Дык в хаскеле паттерн матчинг первичен. Без него язык не Тьюринг полный.

Waterlaz ★★★★ ()
Ответ на: комментарий от den73

вот так ещё лучше

data Fruit = Apple | Orange deriving (Show, Eq)

wdiff w1         w2      | w1 == w2  = "weights are equal"
                         | otherwise = "weights are different"

diff2 (f1, a1)  (f2, a2) | f1 == f2  = "both are of type " ++ show f1 ++ ", " ++ wdiff a1 a2
                         | otherwise = "first is " ++ show f1 ++ ", second is " ++ show f2

AndreyKl ★★★★ ()
Ответ на: комментарий от Waterlaz

То что называют хаскелисты «паттерн матчингом» таковым не является. Это эквивалент ветвлений, на самом деле, сахар над ветвлениями. Некоторое ограниченное подмножество паттерн-матчинга используется, например, в языках баз данных. А в полной мере эта концепция представлена в декларативных языках, таких как Planner и Prolog, и их производных (conniver etc)

anonymous ()
Ответ на: комментарий от Waterlaz

Тут надо определится что такое «является». Видимо, все таки надо ориентироваться на те источники, которые эту терминологию ввели в употребление в CS — Хьюитт, Ковальски etc. Если ориентироваться на текущий информационный фон, представленый разного рода бложеками, *мнениями*, *версиями*, то, возможно и не является.

anonymous ()
Ответ на: комментарий от AndreyKl

Думал, что проявится такая проблема, как необходимость повтора тегов. Она в первом варианте и была. Но в последующем варианте ты от этого избавился - это годнота.

den73 ★★★★ ()
Ответ на: комментарий от den73

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

data Ao = Apple Int | Orange Int

difference :: Ao -> Ao -> String
difference (Apple a)  (Apple b)  | a == b    = "both are apples, weights are equal"
                                 | otherwise = "both are apples, but weights are different"
difference (Orange a) (Orange b) | a == b    = "both are oranges, weights are equal"
                                 | otherwise = "both are oranges, but weights are different"
difference (Apple _) _                       = "first is apple, second is orange"
difference _ _                               = "first is orange, second is apple"


Это считается за повторение?

Потом код короче из за того что стало можно сравнивать if(Apple == Orange) и просто конвертировать в строку. В данном варианте этого «чита» нет, чистый паттерн матчинг для фруктов.

AndreyKl ★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 2)