Re[23]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 29.11.13 22:10
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


Неплохо бы посмотреть исходный код на другом языке.
Ну и можно попросить D.Mon (так как у меня идрис не стоит, а под Windows я не собрал, и не уверен, что получится) проверить код для такого случая:

myType : Nat -> Type
myType Z = Int
myType (S x) = List (myType x)

create : (n:Nat) -> myType n
create Z = 0
create (S x) = [create x]

useValue : (n:Nat) -> myType n -> String
useValue Z v = show v
useValue (S x) v = concat $ map (useValue x) v

main : IO ()
main = do
  ns <- getLine
  let n = cast ns
  putStrLn $ useValue n (create n)
Re[24]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 06:12
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, Воронков Василий, Вы писали:


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


VE>Неплохо бы посмотреть исходный код на другом языке.


На каком?

VE>Ну и можно попросить D.Mon (так как у меня идрис не стоит, а под Windows я не собрал, и не уверен, что получится) проверить код для такого случая:


VE>
VE>myType : Nat -> Type
VE>myType Z = Int
VE>myType (S x) = List (myType x)

VE>create : (n:Nat) -> myType n
VE>create Z = 0
VE>create (S x) = [create x]

VE>useValue : (n:Nat) -> myType n -> String
VE>useValue Z v = show v
VE>useValue (S x) v = concat $ map (useValue x) v

VE>main : IO ()
VE>main = do
VE>  ns <- getLine
VE>  let n = cast ns
VE>  putStrLn $ useValue n (create n)
VE>


А вы сами можете доказать корректность этой программы "статически"?
Re[21]: Неправильное введение в функциональное программирование
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 30.11.13 07:18
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ну, правильно, ты поменял код и устранил зависимость от рантайм значений. И что ты хотел этим доказать? Понятно, что аналогичную программу можно написать на любом языке. Она приводилась в качестве примера реализации.


Какую еще зависимость? Примера реализации чего?
Я перевел твою программу дословно. В ней ровно столько зависимости от рантайм значений, сколько в оригинале. Если в статически типизированной версии такой зависимости не усматривается, это лишь потому, что ее не было в исходном варианте.
Re[21]: Неправильное введение в функциональное программирование
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 30.11.13 07:38
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>>>Функция типизируется в момент первого применения.

DM>>Звучит как немерлизм, ни в одном нормальном языке такого нет (чтобы именно первого).

ВВ>Никакой это не немерлизм. Это, может, в OCaml не так, где не потрудились ХМ допилить. А в языках с полиморфными операторами ты даже функцию "sum x y =x+y" иначе не типизируешь. Ибо какой у нее тип?


Ну, дядь, ты сейчас говоришь как человек, который хаскеля и других ФЯ в глаза не видел.
Prelude> let sum x y = x + y
Prelude> :t sum
sum :: Num a => a -> a -> a

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

DM>>Ну что значит нет? Значение v тут один раз создается и передается. Какого оно типа? Зависит от того, как мы программу запустили, что ей передали. Это и есть зависимость от рантайма в чистом виде, а не твои странные определения.


ВВ>Ну да.

ВВ>x = 2
ВВ>Это тоже рантайм значение. Вот только известно оно в компайл-тайме.
ВВ>Повторяю — зависимость от рантайм-значений означает зависимость от значений, которые *известны* только в рантайме.

Я тоже повторяю, в моем примере значения именно такие. Они *известны* только в рантайме. Вовсе не как в "x=2".
Давай еще 10 раз повторим, для закрепления.

ВВ>Диапазон значений известен в компайл, соответственно, всё просчитывается статически.


Да. Но сами конкретные значения не известны, в этом вся суть.

ВВ>Там была зависимость от длины списка. Для доказательства корректности достаточно было того, чтобы длина была длиной именно списка, что компилятор прекрасно видел в коде "length xs" и "fun xs".


Все правильно.
Как видим, о рантайм значениях можно рассуждать статически. Сюрприз!

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


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

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


На практике с хорошей системой типов придумать такой код очень сложно. Тебе вот не удалось пока.
Знаешь, что сейчас происходит в математике последние несколько лет? Ее основания и весь фундамент переписывают на Coq и Agda, языках с зависимыми типами, потому что оказалось, что эти системы типов и есть фундамент математики, намного адекватнее теории множеств (которая там как частный случай выводится). Если о программе можно как-то рационально рассуждать, то эти рассуждения можно выразить в тех типах.
http://homotopytypetheory.org/
Единственный минус — пока это довольно сложно делать.
Re[23]: Неправильное введение в функциональное программирование
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 30.11.13 07:46
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Но на всякий случай повторюсь, чтобы не раздувать лишний флейм — речь шла о том, что "типизация по месту" это прямь какая-то кривь и немерлизм. Однако нет. Нормальная практика.


Не, одно дело уточнение типа вызова функции, и совсем другое — сама "функция типизируется в момент первого применения". Вторая фраза предполагает, что до первого применения у функции нет типа, а во время второго применения ее тип уже определен первым. Это полная ересь в ЯП с полиморфизмом.

ВВ>Или я не прав и круче зависимых типов только яйца?


Да, вывод именно такой, конечно.
Хотя исходный посыл был скромнее: то, что выглядит "невозможным" для одних статически типизированных языков, еще не обязятально невозможно для статической типизации как таковой, и со всеми предложенными в статье и обсуждении задачами языки вроде Идриса могут справиться статически.
Re[24]: Неправильное введение в функциональное программирование
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 30.11.13 08:03
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Ну и можно попросить D.Mon (так как у меня идрис не стоит, а под Windows я не собрал, и не уверен, что получится) проверить код для такого случая:


В твоем варианте на выходе всегда одно и то же, т.к. все вложенные списки просто разворачиваются, не меняя строки. Я добавил вывод скобок, чтобы была видна вложенность. И еще один cast добавил, т.к. прямого из String в Nat не было.

... -- myType и create как в оригинале
useValue : (n:Nat) -> myType n -> String
useValue Z v = show v
useValue (S x) v = "[" ++ (concat $  map (useValue x) v) ++ "]"

main : IO ()
main = do
  ns <- getLine
  let n = cast . cast $ ns
  putStrLn $ useValue n (create n)


Компиляем, запускаем:
C:\prog\idris>idris nlist.idr -o nlist.exe

C:\prog\idris>nlist
1
[0]

C:\prog\idris>nlist
0
0

C:\prog\idris>nlist
4
[[[[0]]]]

C:\prog\idris>nlist
42
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

Имеем значение типа List List List .... Int, где число вложенностей зависит от введенного рантайм значения.

В винде если есть MinGW и Haskell Platform, сборка Идриса последней версии (0.9.10) должна быть не шибко сложнее
cabal install idris
Раньше зависимостей было больше, сейчас некоторые из них сделали опциональными.
Разве что пара сишных либ вроде gmp и pthreads может еще требоваться, он они в MinGW легко добавляются.
Re[25]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 30.11.13 09:09
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

VE>>Ну и можно попросить D.Mon (так как у меня идрис не стоит, а под Windows я не собрал, и не уверен, что получится) проверить код для такого случая:


VE>>
VE>>myType : Nat -> Type
VE>>myType Z = Int
VE>>myType (S x) = List (myType x)

VE>>create : (n:Nat) -> myType n
VE>>create Z = 0
VE>>create (S x) = [create x]

VE>>useValue : (n:Nat) -> myType n -> String
VE>>useValue Z v = show v
VE>>useValue (S x) v = concat $ map (useValue x) v

VE>>main : IO ()
VE>>main = do
VE>>  ns <- getLine
VE>>  let n = cast ns
VE>>  putStrLn $ useValue n (create n)
VE>>


ВВ>А вы сами можете доказать корректность этой программы "статически"?


Конечно. Вы и сами можете пройтись по всем вариантам. Не понимаю, чем вам не нравится bool, но устраивает Nat, у которого тоже два варианта: 0 или (1 + n), правда порождают они бесконечное кол-во вариантов, ну и что.
Re[22]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 09:45
Оценка:
Здравствуйте, D. Mon, Вы писали:

ВВ>>Ну, правильно, ты поменял код и устранил зависимость от рантайм значений. И что ты хотел этим доказать? Понятно, что аналогичную программу можно написать на любом языке. Она приводилась в качестве примера реализации.

DM>Какую еще зависимость? Примера реализации чего?
DM>Я перевел твою программу дословно. В ней ровно столько зависимости от рантайм значений, сколько в оригинале. Если в статически типизированной версии такой зависимости не усматривается, это лишь потому, что ее не было в исходном варианте.

Ну зачем же обманывать? Моя программа работает корректно благодаря рантайм проверке типа, ты, конечно же, ее устранил, но теперь оказывается, что программа была переведена "дословно". Это нормальный подход к дискуссии для тебя?
Re[25]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 30.11.13 09:49
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>В винде если есть MinGW и Haskell Platform, сборка Идриса последней версии (0.9.10) должна быть не шибко сложнее


Haskell Platform не канонично. Haskell у меня, конечно есть.

DM>cabal install idris

DM>Раньше зависимостей было больше, сейчас некоторые из них сделали опциональными.
DM>Разве что пара сишных либ вроде gmp и pthreads может еще требоваться, он они в MinGW легко добавляются.

Не хватало make, после установки через Cygwin cabal install idris собрало idris.exe и кучу .idr файлов, но затем рухнуло на:

cc -fPIC -O2 -Wall -I/usr/local/include -c -o idris_rts.o idris_rts.c
process_begin: CreateProcess(NULL, cc -dumpmachine, ...) failed.
process_begin: CreateProcess(NULL, cc -fPIC -O2 -Wall -I/usr/local/include -c -o idris_rts.o idris_rts.c, ...) failed.
make (e=2): ▒▒ ▒▒▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒ ▒▒▒▒.
make: *** [idris_rts.o] ▒▒▒▒▒▒ 2

Положил idris.exe в libs/prelude, интерпретатор запускается. Но что-то там явно не доделало, скомпилировать простой пример не удается.

C:\Users\Alexandr\AppData\Roaming\cabal\i386-windows-ghc-7.6.3\idris-0.9.10\rts\idris_main.c: openFile: does not exist (No such file or directory)
Re[22]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 09:59
Оценка: -1
Здравствуйте, D. Mon, Вы писали:

DM>Ну, дядь, ты сейчас говоришь как человек, который хаскеля и других ФЯ в глаза не видел.

DM>
DM>Prelude> let sum x y = x + y
DM>Prelude> :t sum
DM>sum :: Num a => a -> a -> a
DM>

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

Да нет, сынок, это ты сейчас говоришь как человек, который "других ФЯ" в глаза не видел. Причем довольно известных. Например, F#.

DM>>>Ну что значит нет? Значение v тут один раз создается и передается. Какого оно типа? Зависит от того, как мы программу запустили, что ей передали. Это и есть зависимость от рантайма в чистом виде, а не твои странные определения.


ВВ>>Ну да.

ВВ>>x = 2
ВВ>>Это тоже рантайм значение. Вот только известно оно в компайл-тайме.
ВВ>>Повторяю — зависимость от рантайм-значений означает зависимость от значений, которые *известны* только в рантайме.

DM>Я тоже повторяю, в моем примере значения именно такие. Они *известны* только в рантайме. Вовсе не как в "x=2".

DM>Давай еще 10 раз повторим, для закрепления.

Да повторяй хоть сотни раз. В твоей трактовке сам термин "зависимость от рантайм-значений" теряет всякий смысл. Я уже множество раз, разными словами, пытался объяснить, какой смысл я вкладываю в это утверждение. Мы зависим от рантайма только в том случае, когда не можем рассуждать о возможных значениях статически. Если диапазон нам известен, то все зависимости от рантайма снимаются; нам ведь известно все множество инвариантов, и рантайм тут не привнесет ничего нового.

ВВ>>Диапазон значений известен в компайл, соответственно, всё просчитывается статически.

DM>Да. Но сами конкретные значения не известны, в этом вся суть.

Вообще-то если конкретные значения известны, то обычно и само вычисление не требуется.

ВВ>>Там была зависимость от длины списка. Для доказательства корректности достаточно было того, чтобы длина была длиной именно списка, что компилятор прекрасно видел в коде "length xs" и "fun xs".

DM>Все правильно.
DM>Как видим, о рантайм значениях можно рассуждать статически. Сюрприз!

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

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


DM>Если этой обработки в коде нет, то будет рантайм ошибка, т.е. это именно баг.

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

Обработка означает, что код *может* работать неправильно, мы допускаем это и пишем другой код, который обрабатывает данную ситуацию. Т.е. мы не задаемся вопросом "при каких значениях этот код будет работать?"; у нас другой вопрос — "что делать, когда код не работает?"

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

DM>На практике с хорошей системой типов придумать такой код очень сложно. Тебе вот не удалось пока.

Ой, ладно. Как раз *на практике* "хорошие системы типов" падают там и сям. Кстати, мне кажется, что человеку, который знает Идрис понять паттерны, при которых его система типов будет обламываться, должно быть не очень сложно
А я Идрис не знаю; все, что я могу в данном случае — тыкаться вслепую, пытаясь понять, где его интеллектуальность закончится.
Нет, я могу конечно, приводить более практичные примеры, чем fun. Но ты сам готов переписывать несколько килобайт кода с динамики?

DM>Знаешь, что сейчас происходит в математике последние несколько лет? Ее основания и весь фундамент переписывают на Coq и Agda, языках с зависимыми типами, потому что оказалось, что эти системы типов и есть фундамент математики, намного адекватнее теории множеств (которая там как частный случай выводится). Если о программе можно как-то рационально рассуждать, то эти рассуждения можно выразить в тех типах.

DM>http://homotopytypetheory.org/
DM>Единственный минус — пока это довольно сложно делать.

Это, конечно, хорошо; вопрос, как это все относится к обсуждаемому вопросу.
Re[24]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 10:09
Оценка: -1
Здравствуйте, D. Mon, Вы писали:

DM>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>Но на всякий случай повторюсь, чтобы не раздувать лишний флейм — речь шла о том, что "типизация по месту" это прямь какая-то кривь и немерлизм. Однако нет. Нормальная практика.

DM>Не, одно дело уточнение типа вызова функции, и совсем другое — сама "функция типизируется в момент первого применения".

У тебя есть какая проблема с самим термином, который я использовал — "отложенная типизация"? Даже если его и ввел Москаль — то, что? Применим он далеко не только к Немерле. И хорошо подходит далеко не только для Немерле.

DM>Вторая фраза предполагает, что до первого применения у функции нет типа, а во время второго применения ее тип уже определен первым. Это полная ересь в ЯП с полиморфизмом.


Вторая фраза предполагает, что до первого применения типизация функции не завершена. На самом деле совершенно неважно, произведена ли типизация до этого частично или же вообще не произведена. Пока у тебя тип функции выглядит как "хз_что->хз_что->хз_что", скомпилирована она не будет.
А полная ересь — рассуждать обо всех языках на основе каких-то конкретных.
Вот F# (заметь, не Немерле) "во время второго применения тип функции уже определен первым":

> let sum x y = x+y
let x = sum 2 3
let y = sum "one," "two";;

  let y = sum "one," "two";;
  ------------^^^^^^

stdin(3,13): error FS0001: В данном выражении требовалось наличие типа
    int    
, но получен тип
    string


и соответственно:

> let sum x y = x+y
sum "One," "Two"
sum 1 2;;

  sum 1 2;;
  ----^

stdin(3,5): error FS0001: В данном выражении требовалось наличие типа
    string    
, но получен тип
    int


Наверное, все потому что F# "не относится" к "ЯП с полиморфизмом"

Теперь вернемся к нашим баранам. То, что происходит в Идрисе — это по сути доказательство функции по месту ее первого применения. Вот только доказательство по сути и является частью типизации.

ВВ>>Или я не прав и круче зависимых типов только яйца?


DM>Да, вывод именно такой, конечно.

DM>Хотя исходный посыл был скромнее: то, что выглядит "невозможным" для одних статически типизированных языков, еще не обязятально невозможно для статической типизации как таковой, и со всеми предложенными в статье и обсуждении задачами языки вроде Идриса могут справиться статически.
Re[22]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 11:31
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>На практике с хорошей системой типов придумать такой код очень сложно. Тебе вот не удалось пока.


Давай даже так. Я, как говорится, не настаиваю, но вдруг тебе делать будет нечего — или самому захочется проверить. Есть задача, воспроизвести некую библиотеку на Ela, которая позволяет писать следующее:

open espec

test1 =
  test "With list"
  given [1]
    when (++) [2]
    should be [1,2]
    when tail
    shouldn't be [1,2]
    should be [2]

test2 = 
  test "With int"
  given 4
    when (+) 5
    should be 9
    when negate
    should be -9
    when (+) 13
    should be 4

[] 
  |> addTest test1
  |> addTest test2
  |> run
  |> formatResult


Вывод:

Test session started.

Test "With list" (failed 0, errors 0):
  given [1]
    when (++) [2] -> [1,2]
    should be [1,2] -> success
    when tail -> [2]
    shouldn't be [1,2] -> success
    should be [2] -> success

Test "With int" (failed 0, errors 0):
  given 4
    when (+) 5 -> 9
    should be 9 -> success
    when negate -> -9
    should be -9 -> success
    when (+) 13 -> 4
    should be 4 -> success

Total tests:2 Failed: 0


Кстати, этот код можно даже исполнить в онлайн-репле.

Я готов пойти на некоторые уступки — в частности, если будут проблемы с красивым выводом. Но общий смысл подхода (и желательно — синтаксис) должен сохраниться.
У нас есть функция test, которая принимает все подряд — т.е. внутри спецификации теста на самом деле одна апликация. Данная функция ничего не исполняет, а формирует некое дерево, как бы AST нашего DSL-я. Работать она может при этом с любыми значениями. У DSL-я есть определенная грамматика — для простоты пусть она будет ограничена тем что и как приводится в примерах. Сначала идет given, после него значение, а после этого либо трансформация значения (when), либо ассерты (should be, shouldn't be). Заметь при этом, что "трансформатор" when может принимать любое кол-во аргументов — корректно и "when negate" и "when (+) 2" — требуемое кол-во аргументов определяется динамически. Ну и соответственно длина конкретного теста может быть любой.

После того как наш AST сформирован, он может быть интерпретирован через функцию run. Функция возвращает структуру данных, описывающую результат. Ну, далее понимаешь.
Могу привести реализацию модуля espec на Ela, если это нужно.
Re[22]: Неправильное введение в функциональное программирование
От: AlexRK  
Дата: 30.11.13 11:48
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>>>Ну что значит нет? Значение v тут один раз создается и передается. Какого оно типа? Зависит от того, как мы программу запустили, что ей передали. Это и есть зависимость от рантайма в чистом виде, а не твои странные определения.

ВВ>>Диапазон значений известен в компайл, соответственно, всё просчитывается статически.
DM>Да. Но сами конкретные значения не известны, в этом вся суть.
DM>Как видим, о рантайм значениях можно рассуждать статически. Сюрприз!

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

  type Range_Type is range -5 .. 10;


Вроде как не зависимый тип, но по сути то же самое. Достаточно мощный решатель может статически проверить соответствие рангу, в том числе с помощью предусловий-постусловий.

В зависимых типах мы точно также везде имеем дело с некоторым "набором допустимых значений", а в том месте, где этот набор схлопывается в конкретное значение — надо ставить if или аналог.
Re[25]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 30.11.13 12:09
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, D. Mon, Вы писали:


ВВ>У тебя есть какая проблема с самим термином, который я использовал — "отложенная типизация"? Даже если его и ввел Москаль — то, что? Применим он далеко не только к Немерле. И хорошо подходит далеко не только для Немерле.


Да, потому что типизируется всё сразу. "Отложенная типизация", это def x = Foo(), а потом по ходу кода уже видно, какой именно Foo, Foo[Int] или какой-то ещё.
Здесь типизация выводится сразу после объявления.
Re[25]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 30.11.13 12:11
Оценка: -1 :)
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Вторая фраза предполагает, что до первого применения типизация функции не завершена. На самом деле совершенно неважно, произведена ли типизация до этого частично или же вообще не произведена. Пока у тебя тип функции выглядит как "хз_что->хз_что->хз_что", скомпилирована она не будет.


Не несите такой откровенной ерунды.

module Test (foo) where
foo x = x


Компилируется. Функция там одна, работает отлично. Разберитесь уже наконец в вопросе.
Re[25]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 30.11.13 12:12
Оценка: -1 :)
Здравствуйте, Воронков Василий, Вы писали:
ВВ>
>> let sum x y = x+y
ВВ>let x = sum 2 3
ВВ>let y = sum "one," "two";;

ВВ>  let y = sum "one," "two";;
ВВ>  ------------^^^^^^

ВВ>stdin(3,13): error FS0001: В данном выражении требовалось наличие типа
ВВ>    int    
ВВ>, но получен тип
ВВ>    string  
ВВ>


ВВ>и соответственно:


ВВ>
>> let sum x y = x+y
ВВ>sum "One," "Two"
ВВ>sum 1 2;;

ВВ>  sum 1 2;;
ВВ>  ----^

ВВ>stdin(3,5): error FS0001: В данном выражении требовалось наличие типа
ВВ>    string    
ВВ>, но получен тип
ВВ>    int    
ВВ>


ВВ>Наверное, все потому что F# "не относится" к "ЯП с полиморфизмом"


А теперь то же самое в Haskell попробуйте. Попробуйте-попробуйте.
Re[26]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 12:17
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>Вторая фраза предполагает, что до первого применения типизация функции не завершена. На самом деле совершенно неважно, произведена ли типизация до этого частично или же вообще не произведена. Пока у тебя тип функции выглядит как "хз_что->хз_что->хз_что", скомпилирована она не будет.


VE>Не несите такой откровенной ерунды.


VE>
VE>module Test (foo) where
VE>foo x = x
VE>


VE>Компилируется. Функция там одна, работает отлично. Разберитесь уже наконец в вопросе.


Разобраться в вопросе нужно вам. F#, когда тип функции невозможно вывести из применения, либо делает ее полиморфной, либо вообще использует политику "default int":


> let sum x y =x+y;;

val sum : x:int -> y:int -> int


Что как бы не исключает вышесказанного. Хаскелл, о котором в процитированном вами сообщении, речи вообще не шло, по умолчанию делает все функции полиморфными.
Это помогло или сейчас будет очередная истерика в стиле самодовольного невежества?
Re[26]: Неправильное введение в функциональное программирование
От: Воронков Василий Россия  
Дата: 30.11.13 12:19
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, Воронков Василий, Вы писали:

ВВ>>
>>> let sum x y = x+y
ВВ>>let x = sum 2 3
ВВ>>let y = sum "one," "two";;

ВВ>>  let y = sum "one," "two";;
ВВ>>  ------------^^^^^^

ВВ>>stdin(3,13): error FS0001: В данном выражении требовалось наличие типа
ВВ>>    int    
ВВ>>, но получен тип
ВВ>>    string  
ВВ>>


ВВ>>и соответственно:


ВВ>>
>>> let sum x y = x+y
ВВ>>sum "One," "Two"
ВВ>>sum 1 2;;

ВВ>>  sum 1 2;;
ВВ>>  ----^

ВВ>>stdin(3,5): error FS0001: В данном выражении требовалось наличие типа
ВВ>>    string    
ВВ>>, но получен тип
ВВ>>    int    
ВВ>>


ВВ>>Наверное, все потому что F# "не относится" к "ЯП с полиморфизмом"


VE>А теперь то же самое в Haskell попробуйте. Попробуйте-попробуйте.


Товарищ, вы вообще не въезжаете, о чем речь или просто покривляться любите? Я довольно хорошо знаю Хаскелл, но при этом совершенно не понимаю, причем тут Хаскелл, когда речь идет о том, что в *некоторых* языках (а не только в Немерле) используется отложенная типизация функций.
Re[27]: Неправильное введение в функциональное программирование
От: VoidEx  
Дата: 30.11.13 12:23
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Что как бы не исключает вышесказанного. Хаскелл, о котором в процитированном вами сообщении, речи вообще не шло, по умолчанию делает все функции полиморфными.

ВВ>Это помогло или сейчас будет очередная истерика в стиле самодовольного невежества?

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

Ну да, легко. Отложенная типизация в действии =)

Re[26]: Неправильное введение в функциональное программирование
От: Klapaucius  
Дата: 30.11.13 12:28
Оценка: +1
Здравствуйте, VoidEx, Вы писали:

VE>А теперь то же самое в Haskell попробуйте. Попробуйте-попробуйте.


Тут под "типизацией по первому применению" подразумевается defaulting/disambiguation которые работают в случае monomorphism/value restriction
Соответственно:

Prelude> sum = \a b -> a + b
sum :: Integer -> Integer -> Integer
Prelude> sum a b = a + b
sum :: Num a => a -> a -> a
Prelude> let sum = \a b -> a + b in sum 2.0 40
42.0
it :: Double


Эффект в F# получается потому, что это, по факту, два языка с разными системами типов. И при переходе из одного в другой работает ограничение на полиморфизм. Соответственно, если оставаться в языке inline-функций типизация пройдет иначе:

> let inline sum x y = x+y;;

val inline sum :
  x: ^a -> y: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)

> let x = sum 2 3;;

val x : int = 5

> let y = sum "one," "two";;

val y : string = "one,two"

> let sum x y = x+y;;

val sum : x:int -> y:int -> int

Легко видеть, что функция типизируется вовсе не по первому применению. И может и обязательно будет типизирована при определении и вовсе без всякого применения.
Ну и в немерле никакой "типизации по месту применения" нет там просто всегда выводится конкретный тип, т.е. ограничение на полиморфизм сильнее чем в хаскеле и даже сильнее велью-рестрикшн в эмэлях.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.