Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π˜Π·ΡƒΡ‡Π°ΠΉ Haskell Π²ΠΎ имя Π΄ΠΎΠ±Ρ€Π°!Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 51

Автор ΠœΠΈΡ€Π°Π½ Π›ΠΈΠΏΠΎΠ²Π°Ρ‡Π°

ΠŸΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΉ способ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ дСйствиС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅,– Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ try:

try :: Exception e => IO a -> IO (Either e a)

Ѐункция try пытаСтся Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ Π΅ΠΉ дСйствиС Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π»ΠΈΠ±ΠΎ Right <Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ дСйствия> Π»ΠΈΠ±ΠΎ Left <ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅>, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

ghci> try (print $ 5 `div` 2) :: IO (Either ArithException ())

2

Right ()

ghci> try (print $ 5 `div` 0) :: IO (Either ArithException ())

Left divide by zero

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Π² Π΄Π°Π½Π½ΠΎΠΌ случаС ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ явно ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏ выраТСния, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ для Π²Ρ‹Π²ΠΎΠ΄Π° Ρ‚ΠΈΠΏΠ° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ нСдостаточно. Помимо ΠΏΡ€ΠΎΡ‡Π΅Π³ΠΎ, ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ позволяСт ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Π½Π΅ всС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ try ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΎ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚:

> try (print $ 5 `div` 0) :: IO (Either IOException ())

*** Exception: divide by zero

Π£ΠΊΠ°Π·Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° SomeException позволяСт ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ любоС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅:

ghci> try (print $ 5 `div` 0) :: IO (Either SomeException ())

Left divide by zero

ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π΄Π²Π° числа Π² Π²ΠΈΠ΄Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки, Π΄Π΅Π»ΠΈΡ‚ ΠΏΠ΅Ρ€Π²ΠΎΠ΅ число Π½Π° Π²Ρ‚ΠΎΡ€ΠΎΠ΅ ΠΈ Π½Π°ΠΎΠ±ΠΎΡ€ΠΎΡ‚ ΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹. НашСй ΠΏΠ΅Ρ€Π²ΠΎΠΉ Ρ†Π΅Π»ΡŒΡŽ Π±ΡƒΠ΄Π΅Ρ‚ коррСктная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибки дСлСния Π½Π° ноль.

import Control.Exception

import System.Environment


printQuotients :: Integer -> Integer -> IO ()

printQuotients a b = do

  print $ a `div` b

  print $ b `div` a


params :: [String] -> (Integer, Integer)

params [a,b] = (read a, read b)


main = do

  args <- getArgs

  let (a, b) = params args

  res <- try (printQuotients a b) :: IO (Either ArithException ())

  case res of

    Left e -> putStrLn "Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° 0!"

    Right () -> putStrLn "OK"

  putStrLn "ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹"

ПогоняСм ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Π½Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… значСниях:

$ ./quotients 20 7

2

0

OK

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

$ ./quotients 0 7

0

Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° 0!

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

$ ./quotients 7 0

Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° 0!

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

ΠŸΠΎΠ½ΡΡ‚Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠΊΠ° эта ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° нСустойчива ΠΊ Π΄Ρ€ΡƒΠ³ΠΈΠΌ Π²ΠΈΠ΄Π°ΠΌ ошибок. Π’ частности, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Β«Π·Π°Π±Ρ‹Ρ‚ΡŒΒ» ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки ΠΈΠ»ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡ… Π½Π΅ Π² Ρ‚ΠΎΠΌ количСствС:

$ ./quotients

quotients: quotients.hs:10:1-31: Non-exhaustive patterns in function params

$ ./quotients 2 3 4

quotients: quotients.hs:10:1-31: Non-exhaustive patterns in function params

Π­Ρ‚ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ гСнСрируСтся ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ params, Ссли ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ Π΅ΠΉ список оказываСтся Π½Π΅ двухэлСмСнтным. МоТно Ρ‚Π°ΠΊΠΆΠ΅ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ нСчисловыС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

$ ./quotients a b

quotients: Prelude.read: no parse

Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ здСсь гСнСрируСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ read, которая Π½Π΅ Π² состоянии ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ Π΅ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΠΊ числовому Ρ‚ΠΈΠΏΡƒ.

Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒΡΡ с Π»ΡŽΠ±Ρ‹ΠΌΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹ΠΌΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌΠΈ, Π²Ρ‹Π΄Π΅Π»ΠΈΠΌ Ρ‚Π΅Π»ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, оставив Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ main ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ:

mainAction :: [String] -> IO ()

mainAction args = do

  let (a, b) = params args

  printQuotients a b


main = do

  args <- getArgs

  res <- try (mainAction args) :: IO (Either SomeException ())

  case res of

    Left e -> putStrLn "Ошибка"

    Right () -> putStrLn "OK"

  putStrLn "ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹"

ΠœΡ‹ Π±Ρ‹Π»ΠΈ Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Ρ‹ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚ΠΈΠΏ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π½Π° SomeException ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ сообщСниС ΠΎΠ± ошибкС ΠΌΠ΅Π½Π΅Π΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ нСизвСстно, ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊΠΎΠ³ΠΎ Π²ΠΈΠ΄Π° Π² Π΄Π°Π½Π½ΠΎΠΌ случаС ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ.

$ ./quotients a b

Ошибка

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

$ ./quotients

Ошибка

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

ΠŸΠΎΠ½ΡΡ‚Π½ΠΎ, Ρ‡Ρ‚ΠΎ Π² ΠΎΠ±Ρ‰Π΅ΠΌ случаС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Π° Π·Π°Π²ΠΈΡΠ΅Ρ‚ΡŒ ΠΎΡ‚ Π΅Ρ‘ Ρ‚ΠΈΠΏΠ°. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ нас имССтся нСсколько ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² для ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ Ρ€Π°Π·Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ²:

handleArith :: ArithException -> IO ()

handleArith _ = putStrLn "Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° 0!"


handleArgs :: PatternMatchFail -> IO ()

handleArgs _ = putStrLn "НСвСрноС число ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки!"


handleOthers :: SomeException -> IO ()

handleOthers e = putStrLn $ "НСизвСстноС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: " ++ show e

К соТалСнию, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ read, Π½ΡƒΠΆΠ½ΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΠΎΠ±Ρ‰ΠΈΠΌ Ρ‚ΠΈΠΏΠΎΠΌ SomeException.

ВмСсто Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° ΠΏΡ€ΠΈ Π°Π½Π°Π»ΠΈΠ·Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° try, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ catch, Π²ΠΎΡ‚ Π΅Ρ‘ Ρ‚ΠΈΠΏ:

ghci> :t catch

catch :: Exception e => IO a -> (e -> IO a) -> IO a

ΠŸΠ Π˜ΠœΠ•Π§ΠΠΠ˜Π•. ΠœΠΎΠ΄ΡƒΠ»ΡŒ Prelude экспортируСт ΡΡ‚Π°Ρ€ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ catch, которая способна ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Π΅Ρ‘ опрСдСлСния, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΈΠΌΠΏΠΎΡ€Ρ‚: import Prelude hiding (catch).

Ѐункция catch ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² дСйствиС ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ: Ссли ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ дСйствия гСнСрируСтся ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ вызываСтся Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ. Π’ΠΈΠΏ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° опрСдСляСт, ΠΊΠ°ΠΊΠΈΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½Ρ‹. Рассмотрим ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… функция mainAction вызываСтся нСпосрСдствСнно Π² GHCi:

ghci> mainAction ["2","0"]

*** Exception: divide by zero

ghci> mainAction ["0","2"] `catch` handleArith

0

Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° 0!

ghci> mainAction ["2","0"] `catch` handleArgs

*** Exception: divide by zero

ghci> mainAction ["2","0"] `catch` handleOthers

НСизвСстноС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: divide by zero

ghci> mainAction ["a", "b"] `catch` handleArgs

*** Exception: Prelude.read: no parse

ghci> mainAction ["a", "b"] `catch` handleOthers

НСизвСстноС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: Prelude.read: no parse

Если строка, выводимая GHCi, начинаСтся с ***, Ρ‚ΠΎ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π½Π΅ Π±Ρ‹Π»ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ΠΎ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ catch инфиксный способ Π²Ρ‹Π·ΠΎΠ²Π°. Π—Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ handleOthers способСн ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ любоС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.

ВСрнёмся ΠΊ основной ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅. Нам хочСтся, Ρ‡Ρ‚ΠΎΠ±Ρ‹ возникшСС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ΠΎ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ подходящим ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ: Ссли ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° ноль, Ρ‚ΠΎ слСдуСт Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ handleArith, ΠΏΡ€ΠΈ Π½Π΅Π²Π΅Ρ€Π½ΠΎΠΌ числС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки – handleArgs, Π² ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… случаях – handleOthers. Π’ этом Π½Π°ΠΌ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ функция catches, посмотрим Π½Π° Π΅Ρ‘ Ρ‚ΠΈΠΏ:

> :t catches

catches :: IO a -> [Handler a] -> IO a

Ѐункция catches ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² дСйствиС ΠΈ список ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² (Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΏΠ°ΠΊΠΎΠ²Π°Π½Ρ‹ конструктором Π΄Π°Π½Π½Ρ‹Ρ… Handler) ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ дСйствия. Если Π² процСссС выполнСния происходит ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ вызываСтся ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈΠ· подходящих ΠΏΠΎ Ρ‚ΠΈΠΏΡƒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² (поэтому, Π² частности, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ handleOthers Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ послСдним). ΠŸΠ΅Ρ€Π΅ΠΏΠΈΡˆΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ main Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π»ΠΈΡΡŒ всС Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ситуации:

main = do

  args <- getArgs

  mainAction args `catches`

                   [Handler handleArith,

                    Handler handleArgs,

                    Handler handleOthers]

  putStrLn "ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹"

ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ, ΠΊΠ°ΠΊ ΠΎΠ½Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚:

$ ./quotients 20 10

2

0

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

$ ./quotients

НСвСрноС число ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки!

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

$ ./quotients 2 0

Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° 0!

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

$ ./quotients a b

НСизвСстноС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: Prelude.read: no parse

ΠšΠΎΠ½Π΅Ρ† ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ ΠΌΡ‹ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Π»ΠΈΡΡŒ с Ρ€Π°Π±ΠΎΡ‚ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ try, catch ΠΈ catches, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΡ… ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Π² Ρ‚ΠΎΠΌ числС ΠΈ возникшСС Π² чистом ΠΊΠΎΠ΄Π΅. Π—Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅ Π΅Ρ‰Ρ‘ Ρ€Π°Π·, Ρ‡Ρ‚ΠΎ вся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π²Ρ‹ΠΏΠΎΠ»Π½ΡΠ»Π°ΡΡŒ Π² Ρ€Π°ΠΌΠΊΠ°Ρ… дСйствий Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‚ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°.

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°

Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° происходят, ΠΊΠΎΠ³Π΄Π° Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ пошло Π½Π΅ Ρ‚Π°ΠΊ ΠΏΡ€ΠΈ взаимодСйствии с внСшним ΠΌΠΈΡ€ΠΎΠΌ Π² дСйствии Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°, ΡΠ²Π»ΡΡŽΡ‰Π΅ΠΌΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ main. НапримСр, ΠΌΡ‹ пытаСмся ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ Ρ„Π°ΠΉΠ», ΠΈ Ρ‚ΡƒΡ‚ оказываСтся, Ρ‡Ρ‚ΠΎ ΠΎΠ½ Π±Ρ‹Π» ΡƒΠ΄Π°Π»Ρ‘Π½, ΠΈΠ»ΠΈ Π΅Ρ‰Ρ‘ Ρ‡Ρ‚ΠΎ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π² этом Π΄ΡƒΡ…Π΅. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΡƒΡŽ Ρ„Π°ΠΉΠ», имя ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ пСрСдаётся Π² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкС, ΠΈ Π³ΠΎΠ²ΠΎΡ€ΡΡ‰ΡƒΡŽ Π½Π°ΠΌ, сколько строк содСрТится Π² Ρ„Π°ΠΉΠ»Π΅:

import System.Environment

import System.IO


main = do

   (fileName:_) <– getArgs

   contents <– readFile fileName

   putStrLn $ "Π’ этом Ρ„Π°ΠΉΠ»Π΅ " ++ show (length (lines contents)) ++

              " ΡΡ‚Ρ€ΠΎΠΊ!"

ΠžΡ‡Π΅Π½ΡŒ простая ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°. ΠœΡ‹ выполняСм дСйствиС Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° getArgs ΠΈ связываСм ΠΏΠ΅Ρ€Π²ΡƒΡŽ строку Π² Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Ρ‘Π½Π½ΠΎΠΌ спискС с ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ fileName. Π—Π°Ρ‚Π΅ΠΌ связываСм имя contents с содСрТимым Ρ„Π°ΠΉΠ»Π°. ΠŸΡ€ΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ lines ΠΊ contents, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ список строк, считаСм ΠΈΡ… количСство ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‘ΠΌ Π΅Π³ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ show, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ строковоС прСдставлСниС числа. Π­Ρ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ – Π½ΠΎ Ρ‡Ρ‚ΠΎ получится, Ссли ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ имя Π½Π΅ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ Ρ„Π°ΠΉΠ»Π°?