Перейти к основному содержимому

Простые приложения на Haskell

Разработчику Архитектору

Простые приложения на Haskell

В Haskell бизнес-логику пишут как чистые функции; IO — на границе программы (файлы, сеть). Сборка: cabal или stack; JSON — aeson.

Как запускать примеры из главы

  1. GHC: ghc имя.hs && ./имя (Linux/macOS) или имя.exe (Windows).
  2. Stack: stack ghc -- имя.hs или проект с stack run.
  3. Нужно: GHC 9+ (ghc --version).

«Генератор паролей» (чистая часть + IO)

Как запустить

  • Файл: password.hs
  • Команда: runhaskell password.hs или ghc -o password password.hs && ./password
import System.Random (randomRs)
import Data.List (nub)

charset :: String
charset = concat [['a'..'z'], ['A'..'Z'], ['0'..'9'], "!@#$%"]

pick :: Int -> String -> [Int] -> String
pick 0 _ _ = []
pick n cs (r:rs) = cs !! (r `mod` length cs) : pick (n-1) cs rs

main :: IO ()
main = do
gen <- newStdGen
let rs = randomRs (0, 10^6) gen
putStrLn $ pick 16 charset rs

Сортировка строк (чисто)

sortLines :: String -> String
sortLines input =
unlines . sort . filter (not . null) . map (filter (not . isSpace)) . lines $ input
where sort = Data.List.sort

Вызов из main: interact sortLines для stdin/stdout.


Калькулятор с Maybe

calc :: Double -> Double -> Char -> Maybe Double
calc a b '+' = Just (a + b)
calc a b '-' = Just (a - b)
calc a b '*' = Just (a * b)
calc a b '/' | b /= 0 = Just (a / b)
calc _ _ '/' = Nothing
calc _ _ _ = Nothing

Трекер задач (aeson)

{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Data.Aeson
import qualified Data.ByteString.Lazy as B

data Task = Task { taskId :: Int, title :: String, done :: Bool }
deriving (Generic, Show, ToJSON, FromJSON)

loadTasks :: FilePath -> IO [Task]
loadTasks path = do
e <- B.readFile path
pure $ either (const []) id (eitherDecode e)

Характерный пример — композиция без циклов

wordCount :: String -> [(String, Int)]
wordCount = map (\w -> (w, length w)) . words

main :: IO ()
main = print $ wordCount "haskell teaches composition"

map, ., words — идиома вместо явных циклов.


См. также: типы и чистота в разделе Haskell

См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).