Здравствуйте, SolVolkov, Вы писали:
SV>IO t -- абстрактный тип данных. Как он там устроен внутри -- детали реализации. SV>Точно так же можно сказать, что у 3 ручка вызова недоступна для посторонних. Причём, совершенно не важно, существует ли такая реализация на самом деле.
Сказать-то можно всё, что угодно. Но зачем запутывать самих себя?
SV>Не понимаю, к чему это всё. Что лично ты понимаешь под функцией в haskell? getChar :: IO Char -- это функция или нет? Если да, то почему f :: Int -- нет?
У слова "функция" есть два смысла.
1) Нечто, превращающее одни значения в другие. Есть аргумент — функция. Нет аргумента — не функция.
2) Нечто, имеющее поведение.
Чтобы избежать этой путаницы, — лично я предпочитаю называть функциями отображения.
Дальше есть три пути, чтобы ввести действия в язык
— отказ от чистоты; неявное время, энергичные вычисления; => изменение дизайна языка
— явное время, т.е. getChar :: Timestamp -> (Char,Timestamp) (или уникальные типы — это то же самое, только в профиль)
— работа через адаптер, который снаружи чист — например, монада State и монада IO, но можно было и не упихивать в формализм монад (ценой синтаксического оверхеда или нового сахара)
Заметим, что
getChar — это действие, возвращающее Char
putStrLn — это не действие, а функция (sic!), отображающая String на действие, возвращающее юнит.
К>Сказать-то можно всё, что угодно. Но зачем запутывать самих себя?
Я пока не услышал, к каким проблемам это приводит
SV>>Не понимаю, к чему это всё. Что лично ты понимаешь под функцией в haskell? getChar :: IO Char -- это функция или нет? Если да, то почему f :: Int -- нет?
К>У слова "функция" есть два смысла. К>1) Нечто, превращающее одни значения в другие. Есть аргумент — функция. Нет аргумента — не функция. К>2) Нечто, имеющее поведение. К>Чтобы избежать этой путаницы, — лично я предпочитаю называть функциями отображения.
А Haskell Report и то и другое называет "функция". Т.е., если я правильно понял твой поинт, ты предлагаешь изменить определение языка. Но это уже совершенно другой вопрос Если твоё предложение пройдёт, то ответ на вопрос в субже станет "нет". А пока...
К>Можно ввести понятие "действие" (action). К>Собственно говоря, его и используют в учебнике К>http://www.haskell.org/haskellwiki/Introduction_to_Haskell_IO/Actions
К>Дальше есть три пути, чтобы ввести действия в язык К>- отказ от чистоты; неявное время, энергичные вычисления; => изменение дизайна языка К>- явное время, т.е. getChar :: Timestamp -> (Char,Timestamp) (или уникальные типы — это то же самое, только в профиль) К>- работа через адаптер, который снаружи чист — например, монада State и монада IO, но можно было и не упихивать в формализм монад (ценой синтаксического оверхеда или нового сахара)
К>Заметим, что К>getChar — это действие, возвращающее Char К>putStrLn — это не действие, а функция (sic!), отображающая String на действие, возвращающее юнит.
Интерестно. Ну, т.е., такая интерпретация мне знакома, но я никогда не думал над тем, что это можно закрепить в определении языка. Просто потому, что это требует более формального рассмотрения (иначе повториться та же ошибка, что и с функциями -- интуитивное введение понятия в язык приводит в разногласиям при толковании).
Определить действие через монады, очевидно, не получится. Более того, за десять минут я не придумал ни одного вменяемого способа определить понятие "действие". Если ты знаешь такой способ -- делись
Здравствуйте, SolVolkov, Вы писали:
К>>У слова "функция" есть два смысла. К>>1) Нечто, превращающее одни значения в другие. Есть аргумент — функция. Нет аргумента — не функция. К>>2) Нечто, имеющее поведение. К>>Чтобы избежать этой путаницы, — лично я предпочитаю называть функциями отображения.
SV>А Haskell Report и то и другое называет "функция". Т.е., если я правильно понял твой поинт, ты предлагаешь изменить определение языка. Но это уже совершенно другой вопрос Если твоё предложение пройдёт, то ответ на вопрос в субже станет "нет". А пока...
Ну, тогда пускай переписывают Introduction у себя на сайте. Или Report переписывают. А то развели барррдак!
К>>Можно ввести понятие "действие" (action).
.....
SV>Интерестно. Ну, т.е., такая интерпретация мне знакома, но я никогда не думал над тем, что это можно закрепить в определении языка. Просто потому, что это требует более формального рассмотрения (иначе повториться та же ошибка, что и с функциями -- интуитивное введение понятия в язык приводит в разногласиям при толковании). SV>Определить действие через монады, очевидно, не получится. Более того, за десять минут я не придумал ни одного вменяемого способа определить понятие "действие". Если ты знаешь такой способ -- делись
Почему не получится?
Во-первых, можно post factum: "Действие — это значение типа IO t. Совершение действия производится оператором >>=".
Или, расширенно, — значения из семейства монад со схожими свойствами: одиночный результат и спрятанные побочные эффекты.
Это State, Reader, Writer, Cont.
В пользу такой трактовки — и слово, используемое в сахаре: do.
К>>>Можно ввести понятие "действие" (action). К>.....
SV>>Интерестно. Ну, т.е., такая интерпретация мне знакома, но я никогда не думал над тем, что это можно закрепить в определении языка. Просто потому, что это требует более формального рассмотрения (иначе повториться та же ошибка, что и с функциями -- интуитивное введение понятия в язык приводит в разногласиям при толковании). SV>>Определить действие через монады, очевидно, не получится. Более того, за десять минут я не придумал ни одного вменяемого способа определить понятие "действие". Если ты знаешь такой способ -- делись
К>Почему не получится? К>Во-первых, можно post factum: "Действие — это значение типа IO t. Совершение действия производится оператором >>=". К>Или, расширенно, — значения из семейства монад со схожими свойствами: одиночный результат и спрятанные побочные эффекты. К>Это State, Reader, Writer, Cont.
К>В пользу такой трактовки — и слово, используемое в сахаре: do.
f :: Monad m => m Int
f = return 1
g1 :: IO Int
g1 = do
a <- f
return $ a + 1
g2 :: [Int]
g2 = do
a <- f
return $ a + 1
f -- это действие или нет? Исходя из твоего определения -- нет (поскольку тип не IO t, а Monad m => m t). Но по месту применения выглядит то как действие (в g1), то как значение (в g2). Получается слишком запутано и бессмысленно.
SV>f -- это действие или нет? Исходя из твоего определения -- нет (поскольку тип не IO t, а Monad m => m t). Но по месту применения выглядит то как действие (в g1), то как значение (в g2). Получается слишком запутано и бессмысленно.
Но ведь и функцией это не назовёшь... Где у списка потайная ручка для вызова?
Причём, в одних случаях (когда мы рассматриваем его просто как значение списочного вида) он должен "возвращать" одно: самого себя, аналогично "функции" 3. А в других (в трактовке монады) — другое: элементы поштучно.
Здравствуйте, Кодт, Вы писали:
SV>>f -- это действие или нет? Исходя из твоего определения -- нет (поскольку тип не IO t, а Monad m => m t). Но по месту применения выглядит то как действие (в g1), то как значение (в g2). Получается слишком запутано и бессмысленно.
К>Но ведь и функцией это не назовёшь... Где у списка потайная ручка для вызова?
В том-то и проблема -- мы не знаем, есть ли эта "ручка для вызова" в общем случае. Это становится ясно только по месту вызова (и то не обязательно). Что, ИМХО, не позволит достаточно ясно определить понятие "действие".
К>Причём, в одних случаях (когда мы рассматриваем его просто как значение списочного вида) он должен "возвращать" одно: самого себя, аналогично "функции" 3. А в других (в трактовке монады) — другое: элементы поштучно.
SV>f :: Monad m => m Int
SV>f = return 1
SV>g1 :: IO Int
SV>g1 = do
SV> a <- f
SV> return $ a + 1
SV>g2 :: [Int]
SV>g2 = do
SV> a <- f
SV> return $ a + 1
SV>
SV>f -- это действие или нет? Исходя из твоего определения -- нет (поскольку тип не IO t, а Monad m => m t). Но по месту применения выглядит то как действие (в g1), то как значение (в g2). Получается слишком запутано и бессмысленно.
Хм... Продолжая в том же духе
import Control.Applicative
f :: Applicative f => f Int
f = pure 1
g1 :: Maybe Int
g1 = f
g2 :: Int -> Int
g2 = f
Похоже, что понятия "функция" и "значение" в haskell вообще невозможно формально разделить. Этот haskell -- такой haskell
Здравствуйте, SolVolkov, Вы писали:
SV>Похоже, что понятия "функция" и "значение" в haskell вообще невозможно формально разделить. Этот haskell -- такой haskell
Читаю я вас, читаю.. Вот разделите вы эти понятия или, наоборот, не разделите. Вам же это, наверное, зачем то нужно? Зачем?
Здравствуйте, lomeo, Вы писали:
L>Здравствуйте, SolVolkov, Вы писали:
SV>>Похоже, что понятия "функция" и "значение" в haskell вообще невозможно формально разделить. Этот haskell -- такой haskell
L>Читаю я вас, читаю.. Вот разделите вы эти понятия или, наоборот, не разделите. Вам же это, наверное, зачем то нужно? Зачем?
Здравствуйте, lomeo, Вы писали:
L>Вам же это, наверное, зачем то нужно? Зачем?
это нужно для определения словаря
к примеру, хвала Моисею Исаевичу Шейнфинкелю:
"Его работа также показала, что функции двух или более аргументов может быть заменена функцией принимающий лишь один аргумент. Механизм такой замены упрощает работу как в терминах комбинаторной логики, так и лямбда-исчисления и позднее назван каррированием, в честь Хаскелла Карри."