     
 


    Haskell:          ,      .       (, , , )   middle-:   , , , ,   IO, , ,    .

  20   ,    ,   ,      .      ,           .

  ,           ,   ,        .





 

     





 1.   HASKELL   



1.1.   Haskell    



Haskell          ,      .      1980-   1990-            .       .



  Haskell:



  (purity).     .                  .

   (lazy evaluation).    ,     .

       (type inference).     .

     -.

   ,  type classes, higher-kinded types, GADTs  ..

      (immutable by default).



  Haskell  20202020- ?



1.      .

2.        (Java, C#, Python, JavaScript, Rust, Scala).

3.    ,  Haskell :  (Standard Chartered, Barclays),  (Cardano), ,  , DevOps-.

4.  : Haskell      ,     .

5.      .



1.2.  vs  



  (C, Java, Python   ):

"  1,   2,   x,   ..."



 :

",   ,    ".



.       .



 ():

sum = 0

for x in list:

if x % 2 == 0:

sum = sum + x * x



  Haskell:

sumOfSquaresOfEvens = sum . map (^2) . filter even



  :

sumOfSquaresOfEvens xs = sum (map (^2) (filter even xs))



     ,   .



1.3.  ,      



  (value)   (expression).

     .

   .

  .

   .

  .



1.4.    



 19871990:  .

 1990:   (Haskell 1.0).

 1998: Haskell 98 (   ).

 2010: Haskell 2010.

 : GHC (Glasgow Haskell Compiler)   ,   (GHC 9.x).

 Cabal  Stack   .

 Hackage    .

 Stackage    .



1.5.    



   , :

         (Python, JavaScript, Java, C++  ..);

    junior-  FP   middle-;

        .



            ,  .



1.6.     



1.  .

2.     GHCi   .

3.  .

4.  .

5.         .



1.7.   



  : haskell.org

  "Learn You a Haskell for Great Good!" (  ).

 "Haskell Programming from First Principles" (,  ).

  GHC  Hoogle (    ).

 Reddit r/haskell, Haskell Discourse, Telegram-.



         .



   1



1.   ,         .

2.  3  ,    ,  .

3.    5 ,   Haskell  ,   ,  .



 2.  , GHCI   



2.1.  GHC  



   20242026    GHCup.



 Linux / macOS:

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh



   :

 ghcup   

 ghc  

 ghci    (REPL)

 cabal   

 stack     (    )



:

ghc --version

ghci



 Windows      WSL2 + GHCup.



2.2.   GHCi



   :



$ ghci

GHCi, version 9.6.x: https://www.haskell.org/ghc/  :? for help

Prelude>



Prelude    ,    .



 :

Prelude> 2 + 2

4

Prelude> 7 * 8

56

Prelude> 2 ^ 10

1024

Prelude> sqrt 16

4.0

Prelude> pi

3.141592653589793



:

Prelude> "Hello, " ++ "Haskell!"

"Hello, Haskell!"



:

Prelude> True && False

False

Prelude> True || False

True

Prelude> not True

False



2.3.   GHCi



:t             

:i                    //

:l .hs              

:r                       

:q                     

:?                     

:set +t                  

:set prompt "?> "       



:

Prelude> :t 5

5 :: Num a => a

Prelude> :t "hello"

"hello" :: String

Prelude> :t True

True :: Bool

Prelude> :t not

not :: Bool -> Bool



2.4.   .hs



  Hello.hs:



-- Hello.hs

module Main where



main :: IO ()

main = putStrLn ", Haskell!"



  :

$ ghc Hello.hs

$ ./Hello

, Haskell!



  runhaskell (   ):

$ runhaskell Hello.hs



2.5.    



-- Simple.hs

module Simple where



double :: Int -> Int

double x = x * 2



square :: Int -> Int

square x = x * x



sumOfSquares :: Int -> Int -> Int

sumOfSquares x y = square x + square y



  GHCi:

$ ghci Simple.hs

*Simple> double 21

42

*Simple> sumOfSquares 3 4

25



2.6.  



  ~/.ghci  :

:set prompt "?> "

:set +t

:set -Wall



 -Wall          .



2.7. Cabal  Stack   



    GHCi  ghc.

  :



  Cabal:

$ cabal init

$ cabal build

$ cabal run



Stack:

$ stack new my-project

$ cd my-project

$ stack build

$ stack exec my-project-exe



     1415        .hs   GHCi.    .



2.8.    



  macOS    Command Line Tools.

  Linux  libgmp, zlib   .

     ghcup set.

  Windows   WSL2.



2.9.   IDE



 VS Code + Haskell extension (  HLS  Haskell Language Server)

 Emacs + haskell-mode

 Vim/Neovim + coc-haskell  haskell-tools.nvim

 IntelliJ + Haskell plugin ( )



HLS  , ,   , type holes   .



   2



1.  GHCup    ghc, cabal, stack.

2.  ,       .

3.     : ,     .   GHCi  .

4.     GHCi.



 3. ,    



3.1.   



 Haskell    ,     .



5                       -- Int ( Num a => a)

True                    -- Bool

'a'                     -- Char

"hello"                 -- String ( [Char])

[1,2,3]                 -- [Int]

(1, "hello", True)      -- (Int, String, Bool)



3.2.  



 Int               ( 64 )

 Integer          

 Float              

 Double         

 Bool          True | False

 Char          

 String          [Char]



:

Prelude> :t 42

42 :: Num a => a

Prelude> :t (42 :: Int)

42 :: Int

Prelude> :t (42 :: Integer)

42 :: Integer



3.3.   



  :

[1,2,3,4] :: [Int]

["a","b"] :: [String]

[]        :: [a]          --    



  ,  :

(1, "hello")           :: (Int, String)

(True, 3.14, 'x')      :: (Bool, Double, Char)

()                     :: ()               -- unit type



3.4.   



   :

not :: Bool -> Bool

length :: [a] -> Int

take :: Int -> [a] -> [a]

(++) :: [a] -> [a] -> [a]



  :

(+) :: Num a => a -> a -> a



3.5. otation 



 Haskell   ,    :



add :: Int -> Int -> Int

add x y = x + y



  :

(5 :: Int) + (7 :: Int)



3.6.  



if  then 1 else 2



:  then,  else ,       .



absolute :: Int -> Int

absolute n = if n >= 0 then n else -n



    :

absolute n =

if n >= 0

then n

else -n



3.7.   (guards)



  guards:



absolute :: Int -> Int

absolute n

| n >= 0    = n

| otherwise = -n



otherwise    True.



 :

bmiTell :: Double -> Double -> String

bmiTell weight height

| bmi <= 18.5 = " "

| bmi <= 25.0 = ""

| bmi <= 30.0 = " "

| otherwise   = ""

where bmi = weight / height ^ 2



3.8. where  let



where     :



cylinder :: Double -> Double -> Double

cylinder r h =

sideArea + 2 * topArea

where

sideArea = 2 * pi * r * h

topArea  = pi * r ^ 2



let  :



cylinder r h =

let sideArea = 2 * pi * r * h

topArea  = pi * r ^ 2

in  sideArea + 2 * topArea



 GHCi let   :

Prelude> let x = 5

Prelude> let y = 7

Prelude> x + y

12



3.9. 



--  



{-





-}



3.10.    



Haskell    (layout rule).



: ,     ,      .



:

let x = 5

y = 7     -- 



:

let x = 5

y = 7



    ( ):

let { x = 5; y = 7 }



3.11.    



 :

2 + 3 * 4     -- 14,   *   



       :

div 10 2

10 `div` 2



      :

(+) 2 3



3.12.   



fst, snd            

head, tail, last, init

null, length

take, drop

reverse

elem

maximum, minimum

sum, product

and, or

zip, zipWith

words, unwords, lines, unlines



:

Prelude> head [1,2,3]

1

Prelude> tail [1,2,3]

[2,3]

Prelude> take 3 [1..10]

[1,2,3]

Prelude> [1..5]

[1,2,3,4,5]

Prelude> [1,3..10]

[1,3,5,7,9]

Prelude> elem 3 [1,2,3,4]

True



   3



1.  ,       (  max).

2.   signum ( ): -1, 0, 1.

3.  ,      .

4.  ,  ,    .

5.  where,       .



 4. , -  



4.1.  



  :

add :: Int -> Int -> Int

add x y = x + y



  :

add5 = add 5

-- add5 :: Int -> Int



4.2. -



     .



  :

factorial :: Integer -> Integer

factorial 0 = 1

factorial n = n * factorial (n - 1)



:    .      .



  :

head' :: [a] -> a

head' [] = error " "

head' (x:_) = x



tail' :: [a] -> [a]

tail' [] = error " "

tail' (_:xs) = xs



 :

length' :: [a] -> Int

length' [] = 0

length' (_:xs) = 1 + length' xs



:

sum' :: Num a => [a] -> a

sum' [] = 0

sum' (x:xs) = x + sum' xs



4.3. as-



   ,   :



capital :: String -> String

capital "" = " "

capital all@(x:xs) = "  " ++ [x] ++ " : " ++ xs



4.4.     case



case  of

1 -> 1

2 -> 2



:

describeList :: [a] -> String

describeList xs = " " ++ case xs of

[]  -> ""

[x] -> "  "

_   -> "  "



4.5.     



 Haskell   for/while   .       .



  ( )   ,  GHC    .



 :

sumTail :: Num a => [a] -> a

sumTail xs = go 0 xs

where

go acc []     = acc

go acc (x:xs) = go (acc + x) xs



4.6.    



zip' :: [a] -> [b] -> [(a,b)]

zip' _ [] = []

zip' [] _ = []

zip' (x:xs) (y:ys) = (x,y) : zip' xs ys



4.7.  



even' :: Int -> Bool

even' 0 = True

even' n = odd' (n - 1)



odd' :: Int -> Bool

odd' 0 = False

odd' n = even' (n - 1)



4.8.    where/let



    :



quicksort :: Ord a => [a] -> [a]

quicksort [] = []

quicksort (x:xs) =

let smaller = filter (<= x) xs

bigger  = filter (> x) xs

in  quicksort smaller ++ [x] ++ quicksort bigger



  where:

quicksort (x:xs) = quicksort smaller ++ [x] ++ quicksort bigger

where

smaller = [a | a <- xs, a <= x]

bigger  = [a | a <- xs, a > x]



4.9.    



error :: String -> a

undefined :: a



    (head, tail, !!  ..)  -.     Maybe  Either.



4.10.    



--  

reverse' :: [a] -> [a]

reverse' [] = []

reverse' (x:xs) = reverse' xs ++ [x]



--    

reverse'' :: [a] -> [a]

reverse'' xs = go [] xs

where

go acc []     = acc

go acc (x:xs) = go (x:acc) xs



--   

(!!) :: [a] -> Int -> a

[] !! _ = error "  "

(x:_) !! 0 = x

(_:xs) !! n = xs !! (n - 1)



-- take

take' :: Int -> [a] -> [a]

take' n _

| n <= 0 = []

take' _ [] = []

take' n (x:xs) = x : take' (n - 1) xs



   4



1.  ,  n-   ( ,   ).

2.   elem   .

3.  ,      ,  .

4.  merge (   ).

5.  ,  ,    .



 5. ,    



5.1.     



:

[1,2,3]

1:2:3:[]          --   

[1..10]

[1,3..20]

['a'..'z']



5.2.  



(++)  :: [a] -> [a] -> [a]     -- 

(:)   :: a -> [a] -> [a]       -- cons

head, tail, last, init

null :: [a] -> Bool

length :: [a] -> Int

reverse :: [a] -> [a]

take, drop, splitAt

elem, notElem

maximum, minimum ( Ord)

sum, product ( Num)

and, or ( [Bool])

any, all

concat :: [[a]] -> [a]

concatMap

zip, zipWith, unzip

words, unwords, lines, unlines



5.3.   (list comprehensions)



    :



[x * 2 | x <- [1..10]]

[x | x <- [1..20], even x]

[(x,y) | x <- [1..3], y <- [1..3]]

[(x,y) | x <- [1..3], y <- [1..3], x + y == 4]



  :

[x | x <- [1..100], x `mod` 3 == 0, x `mod` 5 == 0]



 let :

[x * x | x <- [1..10], let y = x * x, y > 50]



 :

[c | c <- "Hello World", c `elem` ['A'..'Z']]



5.4. 



String = [Char]



      .



"hello" ++ " world"

reverse "haskell"

length ""          --   Unicode!



        Text ( text).



5.5.  



 :



ones = 1 : ones

[1..]

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)



take 20 fibs



5.6.  



--   ( Eq)

nub :: Eq a => [a] -> [a]



-- 

import Data.List (sort)

sort [3,1,4,1,5,9]



-- 

group [1,1,1,2,2,3,3,3,3]



-- 

inits, tails



-- 

transpose [[1,2,3],[4,5,6]]



5.7.   



--  

import Data.List (sort, group)

frequency xs = map (\g -> (head g, length g)) . group . sort $ xs



--   

isAnagram s1 s2 = sort s1 == sort s2



--     

wordCount = length . words



   5



1.  ,        1  n.

2.   list comprehension    10?10.

3.  ,      .

4.  ,       n ( ).

5.        10.



 6.  : MAP, FILTER, FOLD  



6.1.   



     ,        .



map :: (a -> b) -> [a] -> [b]

filter :: (a -> Bool) -> [a] -> [a]

foldr :: (a -> b -> b) -> b -> [a] -> b

foldl :: (b -> a -> b) -> b -> [a] -> b



6.2. map



map (*2) [1..5]          -- [2,4,6,8,10]

map toUpper "haskell"    -- "HASKELL"

map length ["hello", "world"]  -- [5,5]



:

map' :: (a -> b) -> [a] -> [b]

map' _ [] = []

map' f (x:xs) = f x : map' f xs



6.3. filter



filter even [1..10]

filter (>5) [1..10]

filter (/= ' ') "hello world"



:

filter' _ [] = []

filter' p (x:xs)

| p x       = x : filter' p xs

| otherwise = filter' p xs



6.4. foldr  foldl



foldr   :

foldr (+) 0 [1,2,3,4] = 1 + (2 + (3 + (4 + 0)))



foldl   :

foldl (+) 0 [1,2,3,4] = (((0 + 1) + 2) + 3) + 4



       ,        .



sum = foldr (+) 0

product = foldr (*) 1

and = foldr (&&) True

or = foldr (||) False

length = foldr (\_ acc -> acc + 1) 0

reverse = foldl (\acc x -> x : acc) []



6.5. foldl'   



 Data.List  foldl'    fold.     foldl  ,    thunk'.



6.6.   



zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

zipWith (+) [1,2,3] [4,5,6]  -- [5,7,9]



takeWhile, dropWhile

span, break

any, all

find

partition

nubBy, groupBy, sortBy, on



6.7.  



(.) :: (b -> c) -> (a -> b) -> a -> c



f . g = \x -> f (g x)



:

sumOfSquaresOfEvens = sum . map (^2) . filter even



    point-free ():

countEven = length . filter even



6.8. -



\x -> x * 2

\x y -> x + y

\(x,y) -> x + y

\xs -> length xs > 5



6.9.  



(2*)      --   2

(*2)      --  

(>5)      --  > 5

(/10)     --   10

(10/)     -- 10   -



6.10. 



--     5

longWords = length . filter ((>5) . length) . words



--  

average xs = sum xs / fromIntegral (length xs)



--  

normalize xs = map (/ sum xs) xs



   6



1.  map, filter, foldr .

2.  ,          ,   20.

3.   fold  length, reverse, map, filter.

4.  point-free  ,      .

5.  zipWith,    .



 7. ,  ̨   



7.1.   



     

   (encapsulation)

   

  



7.2.  



module Geometry

( sphereVolume

, sphereArea

, cubeVolume

, cubeArea

) where



-- ...



,   ,  .



7.3. 



import Data.List

import Data.List (nub, sort)

import Data.List hiding (nub)

import qualified Data.Map as M

import Data.Map (Map)

import Data.Map as Map



:

import qualified Data.Map as Map

Map.lookup "key" myMap



7.4.  ,   



Prelude            

Data.List

Data.Maybe

Data.Either

Data.Tuple

Data.Char

Data.Map ()

Data.Set

Data.Text ()

Control.Monad

Control.Applicative

System.IO

Text.Printf

  



7.5.  



my-project/

src/

MyProject/

Lib.hs

Types.hs

Utils.hs

Main.hs

test/

my-project.cabal

stack.yaml  ( stack)

README.md



7.6.  



module MyProject.Types where

module MyProject.Utils where

module MyProject.Lib where



import MyProject.Types

import MyProject.Utils



7.7.    



data Point = Point Double Double



--   ,  :

module Geometry (Point) where



--  :

module Geometry (Point(..)) where



--  :

module Geometry (Point(Point)) where



7.8.    



{-# LANGUAGE OverloadedStrings #-}

{-# LANGUAGE FlexibleContexts #-}

{-# LANGUAGE InstanceSigs #-}



   ,  ,   , .



7.9.   



     

    

   

  qualified import    (Map, Set, Text, ByteString)

  import *



   7



1.   Geometry    ,   .   .

2.  ,   qualified import Data.List  Data.Char.

3.     34 .



 II.   



 8.    (ADT)



8.1. data    



data Bool = False | True

deriving (Eq, Ord, Show, Read, Enum, Bounded)



data Color = Red | Green | Blue

deriving (Eq, Show)



data Point = Point Double Double

deriving (Show)



data Shape

= Circle Double

| Rectangle Double Double

| Triangle Double Double Double

deriving (Show)



8.2.   ADT  -



area :: Shape -> Double

area (Circle r) = pi * r * r

area (Rectangle w h) = w * h

area (Triangle a b c) =

let p = (a + b + c) / 2

in sqrt (p * (p - a) * (p - b) * (p - c))



8.3. Record syntax



data Person = Person

{ firstName :: String

, lastName  :: String

, age       :: Int

, height    :: Float

} deriving (Show)



p = Person "" "" 30 1.80



firstName p

age p



 (    ):

p2 = p { age = 31 }



8.4.  



data Maybe a = Nothing | Just a

data Either a b = Left a | Right b

data Tree a = Empty | Node a (Tree a) (Tree a)



8.5.  



data List a = Nil | Cons a (List a)



data Nat = Zero | Succ Nat



data Expr

= Const Int

| Add Expr Expr

| Mul Expr Expr

| Var String



8.6. newtype



newtype Zoom = Zoom Double

deriving (Show)



  data:  runtime   ,   .



newtype Identity a = Identity a

newtype Sum a = Sum a

newtype Product a = Product a



8.7. type  



type String = [Char]

type Name = String

type Point = (Double, Double)

type AssocList k v = [(k, v)]



8.8.  



-- 

newtype Money = Money Integer deriving (Eq, Ord, Show)



-- 

newtype UserId = UserId Int deriving (Eq, Show)

newtype OrderId = OrderId Int deriving (Eq, Show)



-- 

data OrderStatus

= Pending

| Paid

| Shipped

| Delivered

| Cancelled

deriving (Eq, Show)



   8



1.        .

2.   insert, lookup, toList  .

3.   Expr      eval.

4.  record syntax,   ""     .

5.  newtype  Email  Phone   .



 9. TYPE CLASSES: EQ, ORD, SHOW, READ, NUM  



9.1.   type class



Type class    ( ),     .



class Eq a where

(==) :: a -> a -> Bool

(/=) :: a -> a -> Bool

x /= y = not (x == y)     --   



9.2.  



Eq, Ord, Show, Read, Enum, Bounded

Num, Real, Integral, Fractional, Floating, RealFrac, RealFloat



9.3. deriving



data Color = Red | Green | Blue

deriving (Eq, Ord, Show, Read, Enum, Bounded)



 :

Red == Green

Red < Green

show Red

read "Red" :: Color

succ Red

minBound :: Color



9.4.  



instance Eq Color where

Red == Red = True

Green == Green = True

Blue == Blue = True

_ == _ = False



9.5.   



elem :: Eq a => a -> [a] -> Bool

sort :: Ord a => [a] -> [a]

show :: Show a => a -> String



9.6. Num  



(+) (-) (*) negate abs signum fromInteger



 : div, mod, quot, rem

 : (/), recip, fromRational



9.7.   



class Describable a where

describe :: a -> String



instance Describable Bool where

describe True  = ""

describe False = ""



instance Describable Int where

describe n = " " ++ show n



9.8. 



class Eq a => Ord a where

compare :: a -> a -> Ordering

(<) (<=) (>) (>=)

max, min



class Functor f where ...



9.9.  



   deriving (Eq, Show) .

   Map/Set  Ord.

   Read ( ).

  newtype + instance,     (Monoid  Sum/Product).



   9



1.   DaysOfWeek   Eq, Ord, Show .

2.   YesNo (  LYAH)  instances  Bool, Maybe, , Int.

3.  instance Num  ,    ().



 10. MAYBE, EITHER   



10.1.   



head []      runtime exception

"abc" !! 5   exception

div 5 0      exception



            .



10.2. Maybe



data Maybe a = Nothing | Just a



safeHead :: [a] -> Maybe a

safeHead [] = Nothing

safeHead (x:_) = Just x



safeDiv :: Double -> Double -> Maybe Double

safeDiv _ 0 = Nothing

safeDiv x y = Just (x / y)



10.3.   Maybe



fromMaybe :: a -> Maybe a -> a

fromMaybe def Nothing  = def

fromMaybe _ (Just x) = x



maybe :: b -> (a -> b) -> Maybe a -> b

isJust, isNothing

mapMaybe

catMaybes



10.4. Either



data Either a b = Left a | Right b



  Left  , Right  .



safeDivE :: Double -> Double -> Either String Double

safeDivE _ 0 = Left "  "

safeDivE x y = Right (x / y)



10.5.  



  do-     :



f :: Int -> Maybe Int

f x = case safeHead [1..x] of

Nothing -> Nothing

Just y  -> case safeDiv (fromIntegral y) 2 of

Nothing -> Nothing

Just z  -> Just (round z)



 .    Functor, Applicative  Monad.



10.6. Either    ()



 Either    .

   Validation   (semigroupoids  ..)   .



10.7.  



  Maybe/Either    .

  IO-  Control.Exception,  .

      Either   .

    .



   10



1.  safeTail, safeLast, safeInit.

2.   lookup   ,  Maybe.

3.  ,      ( reads)   Either.

4.     ,  Maybe,    .



 11.  (FUNCTOR)



11.1. 



Functor   ,   "" (map over).



class Functor f where

fmap :: (a -> b) -> f a -> f b



 : <$>

fmap = (<$>)



11.2. Instances



instance Functor Maybe where

fmap _ Nothing  = Nothing

fmap f (Just x) = Just (f x)



instance Functor [] where

fmap = map



instance Functor (Either e) where

fmap _ (Left e)  = Left e

fmap f (Right x) = Right (f x)



instance Functor ((->) r) where

fmap = (.)



11.3.  



1. fmap id = id

2. fmap (f . g) = fmap f . fmap g



 ,  fmap   ,    .



11.4. 



fmap (+1) (Just 5)          -- Just 6

fmap (*2) [1,2,3]           -- [2,4,6]

fmap (++ "!") (Right "Hi")  -- Right "Hi!"

fmap length (Just "hello")  -- Just 5



11.5. Functors 



fmap (fmap (*2)) [Just 1, Nothing, Just 3]

-- [Just 2, Nothing, Just 6]



11.6.  



void :: Functor f => f a -> f ()

(<$) :: a -> f b -> f a



   11



1.  instance Functor  Tree a.

2.  instance Functor  Pair a b (   ).

3.     Maybe   .

4.  ,        Either  .



 12. APPLICATIVE



12.1.   Applicative



Functor     .

      ,   ?



class Functor f => Applicative f where

pure :: a -> f a

(<*>) :: f (a -> b) -> f a -> f b



12.2. Maybe



instance Applicative Maybe where

pure = Just

Nothing <*> _ = Nothing

_ <*> Nothing = Nothing

Just f <*> Just x = Just (f x)



:

(+) <$> Just 3 <*> Just 5     -- Just 8

(+) <$> Just 3 <*> Nothing    -- Nothing



12.3. 



instance Applicative [] where

pure x = [x]

fs <*> xs = [f x | f <- fs, x <- xs]



(*) <$> [1,2,3] <*> [10,100]

-- [10,100,20,200,30,300]



12.4. Either



instance Applicative (Either e) where

pure = Right

Left e <*> _ = Left e

_ <*> Left e = Left e

Right f <*> Right x = Right (f x)



12.5.  



liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c

liftA3 ...

*>   <*

sequenceA

traverse

for



12.6.  



    n-     .

   .

   (   ,   ).



   12



1.  instance Applicative  Tree ( ).

2.  ,    Maybe Int   Applicative.

3.  liftA2,      Maybe Double.

4.    fmap  <*> .



 13.  (MONAD)     



13.1. 



class Applicative m => Monad m where

return :: a -> m a          --  ,  pure

(>>=)  :: m a -> (a -> m b) -> m b

(>>)   :: m a -> m b -> m b

m >> k = m >>= \_ -> k



13.2. Maybe  



instance Monad Maybe where

return = Just

Nothing >>= _ = Nothing

Just x  >>= f = f x



   :



safeHead [1,2,3] >>= \x ->

safeDiv (fromIntegral x) 2 >>= \y ->

Just (y * 10)



  do-:



do

x <- safeHead [1,2,3]

y <- safeDiv (fromIntegral x) 2

return (y * 10)



13.3. do-



  :



do

a <- ma

b <- mb

return (a + b)



  :



ma >>= \a ->

mb >>= \b ->

return (a + b)



13.4.   



instance Monad [] where

return x = [x]

xs >>= f = concatMap f xs



do

x <- [1,2,3]

y <- [10,20]

return (x * y)



-- [10,20,20,40,30,60]



   list comprehension.



13.5. Either  



instance Monad (Either e) where

return = Right

Left e  >>= _ = Left e

Right x >>= f = f x



13.6.  



1. return a >>= f  ?  f a

2. m >>= return    ?  m

3. (m >>= f) >>= g ?  m >>= (\x -> f x >>= g)



13.7.  



mapM, mapM_

forM, forM_

sequence, sequence_

when, unless

join

liftM, liftM2 (   <$>  liftA2)

filterM

foldM

replicateM



13.8. Writer, Reader, State   



,  :

 Reader   

 Writer   

 State      

 RWS  



     mtl  transformers.



13.9.     



type Error = String

type Result a = Either Error a



safeDiv :: Double -> Double -> Result Double

safeDiv _ 0 = Left "  "

safeDiv x y = Right (x / y)



compute :: Double -> Double -> Double -> Result Double

compute a b c = do

x <- safeDiv a b

y <- safeDiv x c

return (y + 1)



   13



1.   Maybe  do-   do-.

2.  ,    Maybe   Maybe  (sequence).

3.  mapM   .

4.   ""  Either,   +, -, *, /   .



 III.    (  MIDDLE)



 14. - (IO)    



14.1.  IO 



IO a    , ,  ,    a (, ,  ).



main :: IO ()



14.2.  



putStr, putStrLn, putChar

getLine, getChar, getContents

print          -- putStrLn . show

readFile, writeFile, appendFile

interact



14.3. do-  IO



main = do

putStrLn "  ?"

name <- getLine

putStrLn $ ", " ++ name ++ "!"



14.4. return  pure  IO



return "hello" :: IO String



14.5.   



main = do

content <- readFile "input.txt"

writeFile "output.txt" (map toUpper content)



14.6.  vs  IO



readFile   (      ).

       Data.Text.IO  ByteString + strict.



14.7.   IO



import Control.Exception



try, catch, handle, bracket, finally



bracket      :



bracket

(openFile "file.txt" ReadMode)

hClose

(\h -> do ...)



14.8.   



import System.Environment



main = do

args <- getArgs

prog <- getProgName

...



14.9.  ,   ..



import System.Random

import Data.Time



   14



1.  ,       ,   .

2.   todo-list   (, , ).

3.  ,   .

4.       catch.



 15. ,   



15.1.   



  ,     .

 thunk'.



15.2.  



   (   thunk')

   

    



15.3.  



seq :: a -> b -> b

($!) :: (a -> b) -> a -> b

BangPatterns: f !x = ...

StrictData

foldl'  foldl

deepseq / force



15.4.  



sum [1..10000000]  foldl (+) 0    .

foldl' (+) 0  .



15.5. 



ghc -O2 -prof -fprof-auto Program.hs

./Program +RTS -p



15.6. 



  foldl'  .

        strict-  unboxed types.

   !  record-,   .

 ,   .



   15



1.  foldl  foldl'    (   ).

2.     (data StrictList a = SNil | SCons !a !(StrictList a)).

3.  seq,    .



 16.  (HUNIT, QUICKCHECK, TASTY)



16.1.  



      .



16.2. HUnit  -



import Test.HUnit



test1 = TestCase (assertEqual ""  )



16.3. QuickCheck  property-based testing



import Test.QuickCheck



prop_reverse :: [Int] -> Bool

prop_reverse xs = reverse (reverse xs) == xs



quickCheck prop_reverse



16.4. tasty   



 HUnit, QuickCheck, SmallCheck  .



16.5.    



test-suite  cabal-.



16.6.  



  ,    .

  Arbitrary instances.

   .

    CI.



   16



1.  QuickCheck-      .

2.  HUnit-     Maybe/Either.

3.   test-suite  tasty.



 17.   



17.1. 



Parallelism      .

Concurrency      (   ).



17.2. parallel 



import Control.Parallel.Strategies



parMap, using, rpar, rseq, parList  ..



17.3. async



import Control.Concurrent.Async



concurrently, mapConcurrently, race, withAsync



17.4. STM (Software Transactional Memory)



import Control.Concurrent.STM



        .



17.5.  



forkIO, MVar, Chan, QSem  ..



17.6. 



     Strategies / parallel.

  IO-  async.

      STM.

   MVar,      .



   17



1.       .

2.  ,     URL (  async  http-client).

3.     STM.



 18.     



18.1.   regex  read



    .



18.2. Attoparsec / Megaparsec



Megaparsec       .

Attoparsec    (  ByteString).



18.3.  



satisfy, char, string, takeWhile, many, some, choice, (<|>), try



18.4.   



parseNumber = ...

parseExpr = ...



18.5.   Text  ByteString



Data.Text

Data.Text.Encoding

Data.ByteString

Data.ByteString.Lazy



18.6. JSON  Aeson



decode, encode, FromJSON, ToJSON

deriveJSON



   18



1.     .

2.  CSV-.

3.  FromJSON / ToJSON    .



 19.  ,    



19.1. 



  Hindley-Milner style guide / style guide  Johan Tibell / Facebook  ..

 : camelCase  , PascalCase  .

  .

    .

  .



19.2.  



   IO  .

  - .

   (newtype)     .

  "stringly-typed" .



19.3.  



 Maybe   .

 Either / ExceptT    .

         IO.



19.4. 



 .

     (Vector, HashMap, Text, ByteString).

 Strictness ,  .



19.5. 



Haddock-.

  .



19.6.  



 ReaderT + IO  .

 mtl-  concret monad stacks.

 Free / Final Tagless ( ).

 Effect systems (polysemy, effectful)   .



   19



1.          .

2.  newtype   .

3.     IO.



 20. -    -



20.1.    Middle Haskell-



     IO-.

    Functor / Applicative / Monad / Traversable / Foldable.

   ADT.

   (unit + property).

      .

     .

     Hackage.

  Cabal/Stack, HLS, hoogle.



20.2. -  



1.        / JSON.

2.   -.

3.     .

4.   -  API ( async  aeson).

5.   ( RPG    ).

6.     optparse-applicative.



20.3.  



 : "Haskell in Depth", "Parallel and Concurrent Programming in Haskell", "Algebra-Driven Design".

     YouTube (ZuriHac, Haskell eXchange).

     (aeson, lens, conduit, servant).

   open-source.

  type-level programming, Dependent Haskell, Linear Types ( ).



20.4. 



        middle-.

     ,       .

Haskell  ,       .



!







 A.   GHCi

 B.     Prelude  Data.List

 C.       

 D.     

 E.    



 



,    .

    ,      Haskell.



    

(    300 000 )



   1:    



       .      .



       ,  .

      ,    .



  .



 :     ,   5      .



  (Python-):

count = 0

for word in text.split():

if len(word) > 5 and word[0].isupper():

count += 1



   Haskell:

countLongCapitalized = length

. filter (\w -> length w > 5 && isUpper (head w))

. words



    :

import Data.Char (isUpper)

countLongCapitalized = length . filter ((&&) <$> (>5) . length <*> isUpper . head) . words



     point-free     .



  :

1.     (referential transparency).

2.   ( ).

3.  .

4.  ,    .

5.  .



 (  ):

1.   .

2.     - .

3.  "  "  (   ).



 :

Haskell      -,     .

 ,       (Java Streams, C# LINQ, Rust iterators, Python functools, JavaScript map/filter/reduce),     Haskell  ML- .



   Haskell:

- Standard Chartered   .

- Facebook ()  spam detection (Haxl).

- Cardano  .

- GitHub ()   .

-    fintech  high-assurance systems.



1.8.    



       Python/JavaScript        .

  10   Prelude,     .

 ,         =   .



   2:    GHCI  



  GHCi:



:set -XOverloadedStrings

:set -XFlexibleContexts

:set -Wall

:set -fprint-explicit-foralls

:set -fprint-explicit-kinds



    :

 GHCi  readline,   /, Ctrl+R    .



 :

Prelude> :{

Prelude| let factorial 0 = 1

Prelude|     factorial n = n * factorial (n-1)

Prelude| :}



 :

Prelude> :paste

--  

-- Ctrl+D



  GHCi:

:break 

:trace 

:print 

:force 

:step

:list



      printf-style  ,   .



   :



cabal update

cabal install --lib containers text aeson



  stack.



  Cabal- :



my-lib.cabal:

name: my-lib

version: 0.1.0.0

...

library

exposed-modules: MyLib

hs-source-dirs: src

build-depends: base >= 4.14 && < 5

default-language: Haskell2010



2.10.     



 "command not found: ghc"      PATH  ghcup.

   Cabal  GHC.

  Apple Silicon   Rosetta   .

  Docker     volumes    .



2.11. HLS (Haskell Language Server)



    Haskell-.



:

     

 Type information on hover

 Go to definition

 Find references

 Code actions ( type signature, import  ..)

 Eval  (     )

 Retrie ()



     ghcup  VS Code extension.



   3:     



  Haskell  .



id :: a -> a

id x = x



    .    (ad-hoc polymorphism),    .



    type classes:

sort :: Ord a => [a] -> [a]



  Int  Integer:

Int    (,   ).

Integer    (,  ).



  ,    , Int  Int64 .



 vs :

 23   .

     record syntax   .



Unit type () ,   "   ",     ( IO)     .



Bottom (?):

error, undefined,      bottom.

  bottom   .



    .



 :



-- ,   

foreverFail :: a

foreverFail = foreverFail



--  undefined  

myFunction :: Int -> String

myFunction x = undefined  -- TODO: 



3.13.  



1.  ,     ,      .

2.   clamp (  ).

3.  ,  n-   .

4.  ,      "::".



   4:   - 



-       ,    let, where, case, , do-.



  :



-- 

f (_:_:xs) = xs          --    



-- 

data Tree a = Leaf a | Branch (Tree a) (Tree a)



sumTree :: Num a => Tree a -> a

sumTree (Leaf x) = x

sumTree (Branch l r) = sumTree l + sumTree r



--   guards

describe n

| n == 0    = ""

| n == 1    = ""

| even n    = ""

| otherwise = ""



   :



GHC    tail call optimization   ,  Scheme,     (    strictness)   .



   ( ):

fac 0 = 1

fac n = n * fac (n-1)



:

fac n = go n 1

where

go 0 acc = acc

go n acc = go (n-1) (n*acc)



   bang pattern:

go 0 !acc = acc

go n !acc = go (n-1) (n*acc)



4.11.  



1.  ,    .

2.       ( ).

3.  ,   n-         .

4.   zipWith  .

5.  ,  ,   .

6.  mergeSort .



   5:   



List comprehensions      map, filter  concatMap.



[x * 2 | x <- [1..10], even x]



map (*2) (filter even [1..10])



  :

[(x,y) | x <- [1..3], y <- [1..3]]



concatMap (\x -> map (\y -> (x,y)) [1..3]) [1..3]



 :



primes = sieve [2..]

where

sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]



      .



 :



--   

pythagorean = [(a,b,c) | c <- [1..]

, b <- [1..c]

, a <- [1..b]

, a^2 + b^2 == c^2]



take 10 pythagorean



  :



import Data.Char



toUpperCase = map toUpper

removeSpaces = filter (/= ' ')

isPalindrome s = s == reverse s



 Unicode   : length "" == 6,      .



5.8.  



1.  ,    .

2.  combinations ().

3.  ,       ().

4.    ,         ()   .

5.  run-length encoding.



   6:    



 point-free    .



:  ,     .

:   ,  .



:  point-free         .,     .



  point-free:

sum = foldr (+) 0

product = foldr (*) 1

or = foldr (||) False

any p = or . map p

all p = and . map p



 point-free ( ):

f = (.) . (.)   --  \g h x -> g (h x)  (  )



    Data.List  Prelude:



iterate :: (a -> a) -> a -> [a]

iterate f x = x : iterate f (f x)



-- :  

take 10 $ iterate (*2) 1



unfoldr   (  foldr)



groupBy, sortBy, nubBy     / .



on  Data.Function:

sortBy (compare `on` length)

groupBy ((==) `on` even)



6.11.  



1.  iterate  .

2.  ,    n .

3.  point-free  ,     .

4.  fold,  transponse   .

5.   sliding window ( ).



   7:    



    :



src/

App/

Main.hs

Lib/

Types.hs

Config.hs

Db.hs

Api.hs

Utils.hs

Lib.hs                  -- 



:



src/

MyApp.hs

MyApp/

Types.hs

Logic.hs

IO.hs



 :

    .

  ,      .



 :

Data.*            

Control.*          (Monad  ..)

System.*           

Network.*        

Text.*           

 ..



7.10.  



       ,     API    .

  ( ) .



   8:   



        Haskell.



:

1.     (make illegal states unrepresentable).

2.  newtype     .

3.  sum types + product types    null.

4.  Maybe  ""  (-1, null, "").



  :

data User = User

{ userId :: Int

, name :: String

, email :: String

, isAdmin :: Bool

, isGuest :: Bool

, age :: Int          -- -1  

}



:

newtype UserId = UserId Int

newtype Email = Email Text

data Role = Admin | Registered | Guest

data Age = UnknownAge | Age Int



data User = User

{ userId :: UserId

, name :: Text

, email :: Email

, role :: Role

, age :: Age

}



    :

data OrderStatus

= Draft

| Confirmed UTCTime

| Shipped UTCTime TrackingNumber

| Delivered UTCTime

| Cancelled UTCTime Reason



   ",   -" .



8.9.  



1.       (, , ).

2.     JSON- ().

3.        .

4.  zipper    .



   9: TYPE CLASSES 



Type classes   ad-hoc polymorphism.



 ,   :



Foldable, Traversable

Monoid, Semigroup

Functor, Applicative, Monad, Alternative

Eq, Ord, Show, Read

Num   

IsString, IsList ( OverloadedStrings / OverloadedLists)



Semigroup  Monoid:



class Semigroup a where

(<>) :: a -> a -> a



class Semigroup a => Monoid a where

mempty :: a

mappend :: a -> a -> a

mappend = (<>)



Instances:

[] , Sum, Product, Any, All, First, Last, Endo, Map, Set  ..



    .



9.10. 



1.  Semigroup  Monoid  ,  min/max.

2.   PrettyPrint  instances   .

3. ,   Num,    instance   (a,a).



   1013: , , , 



        Haskell.



  :

1.   Maybe  Either   .

2.   map / fmap .

3. ,   pure  <*>.

4. ,  >>=   .

5.   do-  .



  :

,  Monad    " ".

   Monad        .



IO       (Maybe, [], Either, State, Reader, Writer, STM, Cont  ..).



  :

  ,          Monad (>>=).

     Applicative.



:

-- Applicative ()

liftA2 (,) (Just 3) (Just "hi")



-- Monad ()

Just 3 >>= \x -> Just (show x ++ "!")



13.10.  



  :

 sequence :: Monad m => [m a] -> m [a]

 mapM :: Monad m => (a -> m b) -> [a] -> m [b]

 filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]

 foldM :: Monad m => (b -> a -> m b) -> b -> [a] -> m b



      do.



   14: IO   



 :  IO   .



 :

     .

 IO-    ,      .



  :

processFile :: FilePath -> IO ()

processFile path = do

content <- readFile path

let lines' = lines content

let counted = map (\l -> (l, length l)) lines'

mapM_ print counted



:

countLengths :: String -> [(String, Int)]

countLengths = map (\l -> (l, length l)) . lines



processFile :: FilePath -> IO ()

processFile path = do

content <- readFile path

mapM_ print (countLengths content)



        ,       .



  :

  bracket  withFile, withBinaryFile  ..



import System.IO

withFile "file.txt" ReadMode $ \h -> do

content <- hGetContents h

...



   :

 Data.Text  Data.Text.IO

 Data.ByteString  Data.ByteString.Lazy

 conduit / pipes / streamly     



   15: 



     Haskell:



1.  +  thunk'.

2.    (  Vector).

3.    (List  Map/HashMap/Set).

4.   -   / sharing.

5.  (boxing)  .



:

 +RTS -s     GC

 +RTS -p   

 +RTS -hc  heap profile

 eventlog + ThreadScope

 criterion  



 :

  foldl' / foldl' strict.

 Bang patterns     .

 Unboxed types (Int#, Vector.Unboxed).

 rewrite rules (  ).

 INLINE / INLINABLE .



15.7.   



1.     foldl, foldl', sum,   Vector.

2.          .

3. ,   Data.Map.Strict vs Data.Map.Lazy.



   1620:   



   middle, :



1.   35 ,   .

2.     23  .

3.       ( ).

4. ,    .

5.    ,   Functor / Monad / Traversable.



  :



 1: CLI- (todo, ,  )  JSON-.

 2:  +    ( +  + if).

 3:  HTTP- +  JSON (,   GitHub API).

 4:  -  scotty  servant (  backend).

 5:    (  , ).



 ,      :



 monad transformers (StateT, ReaderT, ExceptT, RWST)

 mtl vs concrete stacks vs effect systems

 lens / optics (  )

 generics  deriving via

 Template Haskell ()

 FFI ( )

 GHC- ,   



 



Haskell   ,     .

     ,       ,   .



      .

    , ,   .

 .



        !



  



      ,   



    ,   ,  ,     ,      300 000 .



 1.  



1.9.    



    :

1. :   ?  .

2.   :       ,   IO,    ( ).



  :

add x y = x + y

length xs = ...

sort xs = ...



 :

getLine                    --    

putStrLn "hello"           --   

readIORef ref              --   

randomRIO (1,10)           --    



  :

  :        .

  :       (referential transparency).

  :   .

    .



1.10.      



 Haskell        .



   :



readData       :: FilePath -> IO [Record]

filterValid    :: [Record] -> [Record]

transform      :: [Record] -> [Result]

aggregate      :: [Result] -> Summary

writeReport    :: FilePath -> Summary -> IO ()



main = do

records <- readData "input.csv"

let summary = aggregate . transform . filterValid $ records

writeReport "output.txt" summary



 ,    (filterValid ? transform ? aggregate)    IO.



1.11.    



|        |      |  |            |   |

|------------|-------------|-----------|------------------------|-------------|

| Haskell    |           |         |             |           |

| OCaml/F#   |   |        |                  |           |

| Scala      |   |        |                  |     |

| Rust       |          |        |                 |           |

| Kotlin     |          |        |                 |           |

| Python     |          |        |            |          |



1.12.  



1.  ,       .       .

2.     5   5  .

3. ,   random    .

4.  3 ,    ,  3    .



 2.  : GHCI  



2.12.   GHCi (   )



:t / :type            

:i / :info             

:k / :kind             (kind)

:l / :load            

:r / :reload         

:m / :module          

:browse                

:main                 main

:set                  

:unset                

:show bindings         

:show modules          

:show packages        

:def                  

:undef                

:cd                   

:edit                 

:etags                tags

:ctags                ctags



  :kind:

:k Maybe             * -> *

:k Either            * -> * -> *

:k Int               *



2.13.    .ghci 



 ~/.ghci:



:set prompt "?> "

:set prompt-cont "?| "

:set +t

:set -Wall

:set -XOverloadedStrings

:set -XFlexibleContexts

:set -XTypeApplications

:def hoogle \x -> return $ ":!hoogle " ++ x

:def docs \x -> return $ ":!hoogle --info " ++ x



  :

?> :hoogle map

?> :docs fmap



2.14.   Cabal ( workflow)



cabal init --interactive

cabal build

cabal run

cabal test

cabal repl                  -- GHCi   

cabal install --lib some-package

cabal update

cabal freeze                --  

cabal outdated



2.15. Stack workflow



stack new project-name

stack build

stack exec project-name-exe

stack test

stack ghci

stack install

stack upgrade



   2020-  cabal + ghcup,  stack     snapshot' Stackage.



 3.  :   



3.14.    



Int            2^29,  2^63

Int8, Int16, Int32, Int64

Word, Word8 ... Word64      

Integer        

Float, Double

Rational        (Ratio Integer)

Complex Double



:

fromIntegral :: (Integral a, Num b) => a -> b

realToFrac   :: (Real a, Fractional b) => a -> b

fromInteger  :: Num a => Integer -> a

toInteger    :: Integral a => a -> Integer



3.15.      



(&&) || not

== /= < > <= >=

compare :: Ord a => a -> a -> Ordering   -- LT | EQ | GT



min, max



3.16.    where  let



--    

quadratic a b c

| disc < 0  = Nothing

| otherwise = Just (x1, x2)

where

disc = b*b - 4*a*c

sqrtDisc = sqrt disc

x1 = (-b + sqrtDisc) / (2*a)

x2 = (-b - sqrtDisc) / (2*a)



-- let  

let result = let x = 10

y = 20

in x * y + 5

in result



3.17.   



1.   isTriangle a b c.

2.   isRightTriangle a b c (  ).

3.   clamp low high value.

4.  ,    "Fizz", "Buzz", "FizzBuzz"   ( ).

5.  ,     "Dd Hh Mm Ss".

6.  ,       .

7.  ,   .

8.  ,     .



 4.     



    ,          4.



 :



--  1

example1 :: [Int] -> Int

example1 xs = foldr (+) 0 (map (^2) (filter even xs))



--  2

example2 :: Maybe Int -> Maybe Int -> Maybe Int

example2 mx my = do

x <- mx

y <- my

return (x + y)



--  3

example3 :: Either String Int -> Either String Int

example3 e = case e of

Left err -> Left (": " ++ err)

Right n  -> Right (n * 2)



--  4 ()

example4 :: [a] -> [a]

example4 [] = []

example4 [x] = [x]

example4 (x:y:xs) = y : x : example4 xs



--  5 ( )

example5 :: (a -> Bool) -> [a] -> [a]

example5 p = foldr (\x acc -> if p x then x:acc else acc) []



     :

 ,  -   .

  foldl  foldr.

    .

   .

     ,   .

  partial- (head, tail, !!, fromJust).



  :

    .

  type signatures  .

     .

  where   .

   .



  :



1.  ,          (powersets).

2.   groupBy    .

3.    mapAccumL / mapAccumR.

4.  ,         Maybe.

5.  ,        (chunksOf).

6.  zipWith3, zipWith4    fold.

7.  ,        .

8.   unique,    .

9.  intersperse  intercalate .

10.  ,  ,      .



 :



        :

-      ?

-         ?

-    ?

-    point-free      ?



   ,    ""    map / filter / fold / unfold / traverse.



 5.     



    ,          5.



 :



--  1

example1 :: [Int] -> Int

example1 xs = foldr (+) 0 (map (^2) (filter even xs))



--  2

example2 :: Maybe Int -> Maybe Int -> Maybe Int

example2 mx my = do

x <- mx

y <- my

return (x + y)



--  3

example3 :: Either String Int -> Either String Int

example3 e = case e of

Left err -> Left (": " ++ err)

Right n  -> Right (n * 2)



--  4 ()

example4 :: [a] -> [a]

example4 [] = []

example4 [x] = [x]

example4 (x:y:xs) = y : x : example4 xs



--  5 ( )

example5 :: (a -> Bool) -> [a] -> [a]

example5 p = foldr (\x acc -> if p x then x:acc else acc) []



     :

 ,  -   .

  foldl  foldr.

    .

   .

     ,   .

  partial- (head, tail, !!, fromJust).



  :

    .

  type signatures  .

     .

  where   .

   .



  :



1.  ,          (powersets).

2.   groupBy    .

3.    mapAccumL / mapAccumR.

4.  ,         Maybe.

5.  ,        (chunksOf).

6.  zipWith3, zipWith4    fold.

7.  ,        .

8.   unique,    .

9.  intersperse  intercalate .

10.  ,  ,      .



 :



        :

-      ?

-         ?

-    ?

-    point-free      ?



   ,    ""    map / filter / fold / unfold / traverse.



 6.     



    ,          6.



 :



--  1

example1 :: [Int] -> Int

example1 xs = foldr (+) 0 (map (^2) (filter even xs))



--  2

example2 :: Maybe Int -> Maybe Int -> Maybe Int

example2 mx my = do

x <- mx

y <- my

return (x + y)




  .


   .

   ,     (https://www.litres.ru/book/uchitel-nachalnoy/kurs-khaskel-ot-dzhuna-do-midla-74458882/)  .

      Visa, MasterCard, Maestro,    ,   ,     ,  PayPal, WebMoney, ., QIWI ,       .


