
module Main where foo = undefined -- main :: IO () main = do putStrLn "Input a: " a <- getLine -- 1 putStrLn "Input b: " b <- getLine -- 2 print (foo ab) -- pure1arg :: Int -> Int pure1arg = (+ 1) -- , 1 pure2args :: Int -> Int -> Int pure2args = (+) -- , 2 unsafe2args :: Int -> Int -> Int unsafe2args = div -- , 2 foo :: String -> String -> Int foo ab = unsafe2args extraUnsafeE unsafeC -- , where unsafeA :: Int unsafeA = read a -- unsafeB :: Int unsafeB = read b -- unsafeA unsafeC :: Int unsafeC = pure1arg unsafeB -- 1 reallyUnsafeD :: Int reallyUnsafeD = pure2args unsafeA unsafeC -- 2 extraUnsafeE :: Int extraUnsafeE = unsafe2args unsafeA reallyUnsafeD -- 2 . 2 . foo is essentially [no matter what] a mixture of integer division and sums.0 , and the user can enter not the numbers, but the left strings, and when converting strings to numbers can throw out an error. Our code is not safe. module Main where import Control.Exception (IOException, catch) printError :: IOException -> IO () printError = print pure2args :: Int -> Int -> Int pure2args = (+) pure1arg :: Int -> Int pure1arg = (+ 1) unsafe2args :: Int -> Int -> Int unsafe2args ab = if b == 0 then error "Error 'unsafe2args' : wrong 2nd argument = 0" --unsafe source of IOException else div ab foo :: String -> String -> Int foo ab = unsafe2args extraUnsafeE unsafeC where unsafeA :: Int unsafeA = read a --unsafe source of IOException unsafeB :: Int unsafeB = read b --unsafe source of IOException unsafeC :: Int unsafeC = pure1arg unsafeB reallyUnsafeD :: Int reallyUnsafeD = pure2args unsafeA unsafeC extraUnsafeE :: Int extraUnsafeE = unsafe2args unsafeA reallyUnsafeD main :: IO () main = do putStrLn "Input a: " a <- getLine putStrLn "Input b: " b <- getLine catch (print (foo ab)) printError -- IOException Option , in Haskell, it is called Maybe a . import Prelude hiding (Maybe) -- . data Maybe a = Nothing | Just a deriving Show deriving part, we simply say that we ask the compiler to be able to translate our data type into a string. show Nothing == "Nothing" show (Just 3) == "Just 3" Nothing if we have no data, and Just a if it has one. maybeResult2args :: Int -> Int -> Maybe Int maybeResult2args ab = if b == 0 then Nothing --safe else Just (div ab) ... maybeA :: Maybe Int maybeA = readMaybe a --safe maybeB :: Maybe Int maybeB = readMaybe b --safe Nothing , if everything is in order, then Just . pure2args :: Int -> Int -> Int pure2args = (+) safePure2args :: Maybe Int -> Maybe Int -> Maybe Int safePure2args ab = case a of Nothing -> Nothing Just a' -> case b of Nothing -> Nothing Just b' -> Just (pure2args a' b') pure1arg :: Int -> Int pure1arg = (+ 1) safePure1arg :: Maybe Int -> Maybe Int safePure1arg a = case a of Nothing -> Nothing Just a' -> Just (pure1arg a') maybeResult2args :: Int -> Int -> Maybe Int maybeResult2args ab = if b == 0 then Nothing else Just (div ab) foo :: String -> String -> Maybe Int foo ab = case maybeE of Nothing -> Nothing Just e -> case maybeC of Nothing -> Nothing Just c -> maybeResult2args ec where maybeA :: Maybe Int maybeA = readMaybe a maybeB :: Maybe Int maybeB = readMaybe b maybeC :: Maybe Int maybeC = safePure1arg maybeB maybeD :: Maybe Int maybeD = safePure2args maybeA maybeC maybeE = case maybeA of Nothing -> Nothing Just a1 -> case maybeD of Nothing -> Nothing Just d -> maybeResult2args a1 d printMaybe :: Show a => Maybe a -> IO () printMaybe Nothing = print "Something Wrong" printMaybe (Just a) = print a main :: IO () main = do putStrLn "Input a: " a <- getLine putStrLn "Input b: " b <- getLine printMaybe (foo ab) fmap function exists. class Functor f where fmap :: (a -> b) -> fa -> fb (<$>) :: Functor f => (a -> b) -> fa -> fb (<$>) = fmap fmap id == idfmap (f . g) == fmap f . fmap gid is an identity function id :: a -> a id x = x (.) - functional composition (.) :: (b -> c) -> (a -> b) -> a -> c f . g = \x -> f (gx) fmap . Let's look at its arguments - it takes one “pure” function a -> b , we take the “dirty” functor value fa and get the output functor value fb .Maybe is a functor. Create an instance (instance) for the type Maybe , so that the laws of the functors are not violated: instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (fa) Maybe functor? Very simple: safePure1arg :: Maybe Int -> Maybe Int safePure1arg = fmap pure1arg pure1arg function, which means we don’t have to test it again for bugs and everything remained universal and clean, but we easily created its safe version, which accepts not numbers for input, but simple ones numberssafePure2args , we’ll be a fiasco.pure and (<*>) class Functor f => Applicative f where pure :: a -> fa (<*>) :: f (a -> b) -> fa -> fb pure id <*> v == vpure (.) <*> u <*> v <*> w == u <*> (v <*> w)pure f <*> pure x == pure (fx)u <*> pure y == pure ($ y) <*> uf (a -> b) through the functor value. instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing _ <*> Nothing = Nothing (Just f) <*> (Just a) = Just (fa) safePure2args .fmap for the first argument, and the applicative stringing of the remaining arguments: safePure2args :: Maybe Int -> Maybe Int -> Maybe Int safePure2args ab = pure2args <$> a <*> b safePure2args :: Maybe Int -> Maybe Int -> Maybe Int safePure2args ab = (pure pure2args) <*> a <*> b maybeE with the help of applicative functors? Alas.maybeResult2args function:maybeResult2args :: Int -> Int -> Maybe Intreturn and (>>=) functions class Monad m where return :: a -> ma (>>=) :: ma -> (a -> mb) -> mb return a >>= k == kam >>= return == mm >>= (\x -> kx >>= h) == (m >>= k) >>= h (=<<) :: Monad m => (a -> mb) -> ma -> mb (=<<) = flip (>>=) flip :: (a -> b -> c) -> b -> a -> c flip fab = fba Maybe type is a monad, which means we can define its instance (instance): instance Monad Maybe where return = Just (Just x) >>= k = kx Nothing >>= _ = Nothing pure == returnfmap f xs == xs >>= return . fmaybeE maybeE = maybeA >>= (\a1 -> maybeD >>= (maybeResult2args a1)) bind2 function bind2 :: Monad m => (a -> b -> mc) -> ma -> mb -> mc bind2 mf mx my = do x <- mx y <- my mf xy maybeE = bind2 maybeResult2args maybeA maybeD liftM2 and join functions liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> mr join :: Monad m => m (ma) -> ma maybeE = join $ liftM2 maybeResult2args maybeA maybeD do notation: maybeE = do a1 <- maybeA d <- maybeD maybeResult2args a1 d (<$>) :: Functor f => (a -> b) -> fa -> fb (<*>) :: Applicative f => f (a -> b) -> fa -> fb (=<<) :: Monad f => (a -> fb) -> fa -> fb module Main where import Control.Monad import Control.Applicative import Text.Read (readMaybe) bind2 :: Monad m => (a -> b -> mc) -> ma -> mb -> mc bind2 mf mx my = do x <- mx y <- my mf xy pure2args :: Int -> Int -> Int pure2args = (+) pure1arg :: Int -> Int pure1arg = (+ 1) maybeResult2args :: Int -> Int -> Maybe Int maybeResult2args ab = if b == 0 then Nothing --safe else Just (div ab) foo :: String -> String -> Maybe Int foo ab = bind2 maybeResult2args maybeE maybeC where maybeA :: Maybe Int maybeA = readMaybe a --safe maybeB :: Maybe Int maybeB = readMaybe b --safe maybeC :: Maybe Int maybeC = fmap pure1arg maybeB maybeD :: Maybe Int maybeD = pure2args <$> maybeA <*> maybeC maybeE :: Maybe Int maybeE = bind2 maybeResult2args maybeA maybeD printMaybe :: Show a => Maybe a -> IO () printMaybe Nothing = print "Something Wrong" printMaybe (Just a) = print a main :: IO () main = do putStrLn "Input a: " a <- getLine putStrLn "Input b: " b <- getLine printMaybe (foo ab) fmap = map a = do c <- cs d <- ds return (zet cd) a = [zet cd | c <- cs, d <- ds] Source: https://habr.com/ru/post/212955/
All Articles