Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
inums = [0..5]
fnums = [0..5]
main = do
print inums
let fprint = print :: [Double] -> IO ()
fprint fnums
[0,1,2,3,4,5]
[0.0,1.0,2.0,3.0,4.0,5.0]
inum и fnum были присвоены одинаковые выражения, компилятор вывел им разные типы, используя информацию в контексте их использования. Ни C#, ни C++, ни Scala такого не могут. Одна из впечатляющих демонстраций мощи системы типов в Haskell — модуль регулярных выражений, в котором один оператор =~ может возвращать разные типы значений в зависимости от контекста использования, и это всё преспокойно вписывается в систему типов (Regular expressions in Haskell). В RWH есть ещё впечатляющий пример с построением AST из арифметики: Extended example: Numeric Types.неявное преобразование Action к Action
let в коде нужен только для того, чтобы создать контекст, в котором требуется [Double]. Вот другой пример:inum = [0..5]
fnum = [0..5]
sins = map sin
printNums = do
print inum
print $ sins fnum
Prelude> :load "HM.hs"
[1 of 1] Compiling Main ( HM.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t inum
inum :: [Integer]
*Main> :t fnum
fnum :: [Double]
inum и fnum разные статические типы. Т.е. не вставил каст из [Integer] в [Double], а именно изначално присвоил именам правильный статический тип. Он считает, что inum — это список целых, а fnum — список чисел с плавающей точкой, не смотря на то, что им присвоено одно и тоже выражение. У вас же и inum и fnum имеют один и тот же статический тип, компилятор c# считает их оба чем-то вроде IEnumerable<int>.[Double], т.к. [Double] можно проинициализировать числовыми константами и передать в соответствующую функцию.делегаты и локальные лямбды
Итак, вы всё ещё не понимаете Хиндли-Милнера? Часть 1