Purely functional, lazy, strongly typed. Used in finance, academia, and compilers. Write once, reason forever.
main is the entry point. putStrLn prints text. No mutation, no side effects by default.
main :: IO ()
main = do
putStrLn "Hello, World!"
let name = "Mayank"
putStrLn ("Name: " ++ name)
-- Run: ghc hello.hs && ./hello
-- Or: runhaskell hello.hs
-- Types
name :: String
name = "Mayank"
age :: Int
age = 15
pi :: Double
pi = 3.14159
-- Let bindings
result = let x = 10; y = 20 in x + y
-- Where clauses
circleArea r = pi * r * r
where pi = 3.14159
main = do
putStrLn name
print age
print result
print (circleArea 5)
-- Pattern matching
add :: Int -> Int -> Int
add 0 b = b
add a 0 = a
add a b = a + b
-- Guards
bmi :: Double -> String
bmi x
| x < 18.5 = "underweight"
| x < 25 = "normal"
| x < 30 = "overweight"
| otherwise = "obese"
-- Recursion
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
main = do
print (add 3 4)
print (bmi 22.5)
print (factorial 5)
print (fib 10)
Lists are linked. [1,2,3]. List comprehensions generate lists. Infinite lists!
main = do
let nums = [1, 2, 3, 4, 5]
print (head nums) -- 1
print (tail nums) -- [2,3,4,5]
print (length nums) -- 5
print (reverse nums) -- [5,4,3,2,1]
print (take 3 nums) -- [1,2,3]
print (drop 2 nums) -- [3,4,5]
print (nums !! 2) -- 3
-- List comprehension
let squares = [x^2 | x <- [1..10]]
print squares
let evens = [x | x <- [1..20], even x]
print evens
let pairs = [(x,y) | x <- [1..3], y <- [1..3]]
print pairs
-- Infinite list
let naturals = [1..]
print (take 10 naturals)
-- Map, filter, reduce
print (map (*2) nums)
print (filter (>3) nums)
print (foldl (+) 0 nums)
-- Sum type (OR)
data Color = Red | Green | Blue
deriving (Show)
-- Product type (AND)
data Point = Point Double Double
deriving (Show)
-- Complex type
data Shape
= Circle Double
| Rect Double Double
| Triangle Double Double Double
deriving (Show)
area :: Shape -> Double
area (Circle r) = pi * r * r
area (Rect w h) = w * h
area (Triangle a b c) =
let s = (a + b + c) / 2
in sqrt (s * (s-a) * (s-b) * (s-c))
main = do
print (Circle 5)
print (Rect 4 6)
print (area (Circle 5))
print (area (Rect 4 6))
-- Custom type class
class Describable a where
describe :: a -> String
instance Describable Color where
describe Red = "Fire"
describe Green = "Nature"
describe Blue = "Sky"
-- Using type classes
sort :: Ord a => [a] -> [a]
sort [] = []
sort (x:xs) = sort [a | a <- xs, a <= x] ++ [x] ++ sort [a | a <- xs, a > x]
main = do
print (describe Red)
print (sort [3,1,4,1,5,9,2,6])
print (show 42) -- "42"
print (read "42" :: Int) -- 42
print (1 + 2 :: Int) -- 3
IO monad handles side effects. Maybe monad handles failure. do-notation chains actions.
import Control.Monad (when)
-- Maybe monad
safeDivide :: Double -> Double -> Maybe Double
safeDivide _ 0 = Nothing
safeDivide a b = Just (a / b)
-- do-notation with Maybe
calculation :: Maybe Double
calculation = do
a <- safeDivide 10 2
b <- safeDivide a 3
return (a + b)
-- IO monad
main :: IO ()
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello, " ++ name ++ "!")
when (not (null name)) $ do
putStrLn ("Your name has " ++ show (length name) ++ " characters")
print calculation -- Just 8.333...
Functions as values. Composition (.), curry, uncurry. Point-free style.
-- Higher-order functions
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
-- Composition
addOne :: Int -> Int
addOne x = x + 1
double :: Int -> Int
double x = x * 2
-- (.) composes functions right to left
result = (double . addOne) 5 -- double(addOne(5)) = 12
-- Curry/uncurry
add :: Int -> Int -> Int
add a b = a + b
addTuple :: (Int, Int) -> Int
addTuple (a, b) = a + b
main = do
print (applyTwice (+3) 10) -- 16
print (applyTwice (*2) 5) -- 20
print result
print (add 3 4) -- 7
print (uncurry add (3, 4)) -- 7
print (curry addTuple 3 4) -- 7