]]> ]]>
Править | Обсудить | История

Haskell

Дата создания:
1990
Создан под влиянием:
Повлиял на:
Парадигма:
Типизация:
Принятые расширения файлов:
.hs .lhs
Диалекты:
Реализации и версии (свернуть все | развернуть все):
Язык программирования

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 ...

IDE/Редакторы:

Примеры:

Факториал:

Пример для версий 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.4
module 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.4

Haskell предоставляет тип данных для работы с комплексными числами. Функция 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

]]>

Работа программистам