Haskell
- Дата создания:
- 1990
- Создан под влиянием:
- Повлиял на:
- Парадигма:
- Типизация:
- Принятые расширения файлов:
- .hs .lhs
- Диалекты:
- Реализации и версии (свернуть все | развернуть все):
-
- GHC
- Gofer
- HBI и HBC
- Haskell++
- Helium
- Hugs
- Hugs98 for .NET
- Jaskell
- Jhc
- O'Hugs
- Template Haskell
- YHC
- Yale Haskell
-
nhc98
- nhc98 1.04
- nhc98 1.06
- nhc98 1.08
- nhc98 1.10
- nhc98 1.12
- nhc98 1.14
- nhc98 1.14a
- nhc98 1.16
- nhc98 1.18
- nhc98 pre-release 1
- nhc98 pre-release 10
- nhc98 pre-release 11
- nhc98 pre-release 12
- nhc98 pre-release 13
- nhc98 pre-release 14
- nhc98 pre-release 15
- nhc98 pre-release 16
- nhc98 pre-release 17
- nhc98 pre-release 18
- nhc98 pre-release 19
- nhc98 pre-release 2
- nhc98 pre-release 3
- nhc98 pre-release 4
- nhc98 pre-release 5
- nhc98 pre-release 6
- nhc98 pre-release 7
- nhc98 pre-release 8
- nhc98 pre-release 9
- nhc98 release 1.00
- nhc98 release 1.02
Haskell один из наиболее мощных функциональных языков с нестрогой семантикой; получил своё название в честь математика Хаскелла Карри (Haskell Curry). Это один из наиболее популярных и активно развивающихся функциональных языков.
Наиболее важными возможностями Haskell являются:
- Haskell — ленивый (non-strict) язык
- Haskell — чисто функциональный (то есть не содержащий конструкций, неявно зависящих от состояния среды или изменяющих ее)
- Haskell содержит простой и логичных механизм перегрузки функций (известный как “классы типов”). По-видимому, возможные применения этого механизма выходят далеко за рамки решения непосредственной задачи. К примеру, классы типов обеспечивают возможности близкие (в целом — превосходящие), возможностям шаблонов C++, сохраняя при этом возможность раздельной трансляции
- императивные возможности реализуются в Haskell при помощи так называемых монад. Понимание этой конструкции является одной из наибольших проблем при изучении Haskell, но она стоит того, чтобы с ней разобраться
Haskell — превосходный язык для обучения и для экспериментов с сложными функциональными типами данных (многие идеи могут быть выражены непосредственно средствами Haskell).
Программы, написанные на Haskell, имеют значительный размер объектного кода и невысокую скорость исполнения.
Элементы синтаксиса:
Комментарий до конца строки | -- |
---|---|
Комментарии, которые могут быть вложенными | {- ... -} |
Регистрозависимость | да |
Регулярное выражение идентификатора переменной | [_a-z][_a-zA-Z0-9']* |
Группировка выражений | ( ... ) или $ ... |
Блок | { ... } |
Тождественное равенство | == |
Тождественное неравенство | /= |
Сравнение | < > <= >= compare |
Определение функции | f p1 p2 = ... |
Вызов функции | f a b ... |
Вызов функции без параметров | f |
Последовательность | ; или конец строки или >> |
Если - то - иначе | if condition then ... else ... |
Ссылки:
Примеры:
Факториал:
Пример для версий GHC 6.10.4, GHC 6.6.1Используется рекурсивное определение факториала. Пример состоит из трех частей:
-
определение функции
factorial
, принимающей на вход один аргумент типаInteger
(целое число неограниченной точности) и имеющей выход того же типа. Функция определяется рекурсивно, тип параметров задан в явном виде, чтобы избежать неоднозначности их определения. -
определение функции
line
, которая выводит на печать число и его факториал в нужном формате. Использование командыprintf
аналогично языку C++. -
собственно вывод чисел и их факториалов. Для этого командой
[0..16]
создается список чисел от 0 до 16, включительно. Функция двух аргументовmap
применяет первый аргумент (функциюline
) к каждому элементу второго аргумента (списка[0..16]
) и в результате создает список так называемых действий вывода (являющихся в Haskell обычными значениями). Для того, чтобы объединить эти действия в одно, используется командаsequence_
, которая, будучи применена к списку действий, выполняет первое действие из списка и затем рекурсивно применяет себя к хвосту списка.
module Main where
import Text.Printf
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
line x = printf "%d! = %d\n" x $ factorial x
main = sequence_ $ map line [0..16]
Факториал:
Пример для версий GHC 6.6.1Функция fac определена как произведение чисел от 1 до n через встроенную функцию языка product.
module Main where
import Text.Printf
fac n = product [1..n]
main = sequence_ $ map (\x -> printf "%d! = %d\n" x $ fac x) [0..16]
Hello, World!:
Пример для версий GHC 6.10.4module Main where
main = do
putStrLn "Hello, World!"
Числа Фибоначчи:
Пример для версий GHC 6.10.4Этот пример использует одну из основных особенностей языка Haskell — возможность ленивых вычислений и использования бесконечных списков. Бесконечный список чисел Фибоначчи fibs
определяется при помощи фунции zipWith
, которая применяет первый аргумент (функцию двух переменных, в данном случае +
) к парам соответствующих элементов второго и третьего аргументов (списков). tail fibs
возвращает хвост списка fibs
(т.е. все элементы, кроме первого). Таким образом первый элемент списка, возвращаемого zipWith
, является суммой первого и второго элементов списка fibs
и становится третьим его элементом.
module Main where
import Text.Printf
fibs :: [Int]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
line n = printf "%d, " $ fibs !! n
main = do
sequence_ $ map line [1..16]
putStrLn "..."
Числа Фибоначчи:
Пример для версий GHC 6.10.4Этот пример использует рекурсивное определение чисел Фибоначчи через пары соседних чисел в последовательности. На печать выводятся только первые элементы пар.
module Main where
import Text.Printf
fibNextPair :: (Int, Int) -> (Int, Int)
fibNextPair (x, y) = (y, x+y)
fibPair :: Int -> (Int, Int)
fibPair n
| n == 1 = (1, 1)
| otherwise = fibNextPair (fibPair (n-1))
line n = printf "%d, " $ (fst.fibPair) n
main = do
sequence_ $ map line [1..16]
putStrLn "..."
Квадратное уравнение:
Пример для версий GHC 6.10.4Haskell предоставляет тип данных для работы с комплексными числами. Функция quadratic
принимает в качестве аргумента список трех комплексных чисел (коэффициентов уравнения) и возвращает список корней уравнения. Запись вида root sign
позволяет передать знак операции в качестве аргумента и таким образом обобщить запись двух знаков при квадратном корне из дискриминанта.
module Main where
import Data.Complex
import System.IO (hFlush, stdout)
quadratic :: (Complex Double, Complex Double, Complex Double) -> [Complex Double]
quadratic (0, _, _) = []
quadratic (a, b, c)
| d == 0 = [root (+)]
| otherwise = [root (+), root (-)]
where d = b*b - 4*a*c
root sign = sign (-b) (sqrt d) / (2*a)
main = do
putStr "A = "
hFlush stdout
a <- readLn :: IO Double
putStr "B = "
hFlush stdout
b <- readLn :: IO Double
putStr "C = "
hFlush stdout
c <- readLn :: IO Double
print $ quadratic (realToFrac a, realToFrac b, realToFrac c)
Числа Фибоначчи:
Пример для версий GHC 6.8.1Этот пример также использует ленивые вычисления, но иначе формирует вывод нужного формата.
main = putStrLn $ withDots $ join $ take 16 fibs
where fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
join = foldl (\a b -> a ++ show b ++ ", " ) ""
withDots = (++ "...")
Комментарии
]]>blog comments powered by Disqus
]]>