Tsoding

## Imperative style (wrong)

 1 2  10 5

 1 2 3 4 5 6 7 8  solveMeFirst a b = a + b main :: IO () main = do val1 <- readLn val2 <- readLn let sum = solveMeFirst val1 val2 print sum
15


## interact function

Takes a function that takes string and returns a string and applies a side-effect to the output (typically, printing to screen).

 1 2 3  :t interact -- You can write interactive haskell programs in a declarative way -- interact :: (String -> String) -> IO ()
interact :: (String -> String) -> IO ()


## dollar operator

 1  :t ($) ($) :: (a -> b) -> a -> b


We will use this operator to separate interact from its argument.

## Declarative style (correct)

 1  1 2

 1  main = interact $show . sum . map read . words 3  ### Explanation  1  main = interact$

The words function takes a single string and splits it up into tokens (a list of strings).

 1  :t words
words :: String -> [String]

 1 2 3 4 5 6 7 8  -- This wont compile because interact expects -- a function that returns a string, but words -- returns a list of strings -- main :: IO () -- main = interact $words "foo bar baz" main :: IO () main = interact$ words "foo bar baz"
  1 2 3 4 5 6 7 8 9 10  /tmp/file_tempfile_4GR2qL_rand-26110_pid-18248.hs:8:19: error: • Couldn't match expected type ‘String -> String’ with actual type ‘[String]’ • Possible cause: ‘words’ is applied to too many arguments In the second argument of ‘($)’, namely ‘words "foo bar baz"’ In the expression: interact$ words "foo bar baz" In an equation for ‘main’: main = interact $words "foo bar baz" | 8 | main = interact$ words "foo bar baz" | ^^^^^^^^^^^^^^^^^^^

### Troubleshooting

 1  words "foo bar baz"

/tmp/file_tempfile_4xJeY1_rand-14847_pid-15518.hs:1:1: error:
Parse error: module header, import declaration
or top-level declaration expected.
|
1 | words "foo bar baz"
| ^^^^^^^^^^^^^^^^^^^

 1  words "foo bar baz"
["foo","bar","baz"]


A top-level declaration is something like main =.

 1 2 3  main = print (fst (1,2)) >> print (snd (1,2))

## Array sum

hs d
words read tokens
tail remove the first element
map read convert string elements to numbers
sum take the sum
show convert back to string
interact connect the algorithm to stdin and stdout

 1 2  6 1 2 3 4 10 11

 1  main = interact $show . sum . map read . tail . words 31  ## A very big sum The type Integer has arbitrary precision. It automatically scales when the sum grows.  1  :info Integer data Integer = integer-gmp-1.0.2.0:GHC.Integer.Type.S# GHC.Prim.Int# | integer-gmp-1.0.2.0:GHC.Integer.Type.Jp# {-# UNPACK #-}integer-gmp-1.0.2.0:GHC.Integer.Type.BigNat | integer-gmp-1.0.2.0:GHC.Integer.Type.Jn# {-# UNPACK #-}integer-gmp-1.0.2.0:GHC.Integer.Type.BigNat -- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’ instance Eq Integer -- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’ instance Ord Integer -- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’ instance Show Integer -- Defined in ‘GHC.Show’ instance Read Integer -- Defined in ‘GHC.Read’ instance Enum Integer -- Defined in ‘GHC.Enum’ instance Num Integer -- Defined in ‘GHC.Num’ instance Real Integer -- Defined in ‘GHC.Real’ instance Integral Integer -- Defined in ‘GHC.Real’   1 2  5 1000000001 1000000002 1000000003 1000000004 1000000005  1  main = interact$ show . sum . map read . tail . words
5000000015


 1  :t mod
 1  12 mod 5
2

mod :: Integral a => a -> a -> a


 1 2 3 4 5  4 73 67 38 33

  1 2 3 4 5 6 7 8 9 10 11 12 13 14  -- The number we need to get to the next multiple of 5 needfornext5 :: Int -> Int needfornext5 x = 5 - x mod 5 -- m5 = the next multiple of 5 -- | is a condition round5 :: Int -> Int round5 x | x < 38 = x | (m5 - x) < 3 = m5 | otherwise = x where m5 = x + (needfornext5 x) main = interact $unlines . map (show . round5 . read) . tail . words 75 67 40 33  ### Collapsed a condition  1 2 3  -- unlines takes a list of strings and returns a single string -- concatenates all strings, separating with newlines :t unlines unlines :: [String] -> String    1 2 3 4 5 6 7 8 9 10 11 12 13  -- The number we need to get to the next multiple of 5 needfornext5 :: Int -> Int needfornext5 x = 5 - x mod 5 -- m5 = the next multiple of 5 -- | is a condition round5 :: Int -> Int round5 x | x >= 38 && (m5 - x) < 3 = m5 | otherwise = x where m5 = x + (needfornext5 x) main = interact$ unlines . map (show . round5 . read) . tail . words
75
67
40
33


### Can be written like this

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  -- The number we need to get to the next multiple of 5 needfornext5 :: Int -> Int needfornext5 x = 5 - x mod 5 -- m5 = the next multiple of 5 -- | is a condition round5 :: Int -> Int round5 x | x >= 38 && (m5 - x) < 3 = m5 | otherwise = x where m5 = x + (needfornext5 x) solve :: [Int] -> [Int] solve xs = map round5 xs main = interact \$ unlines . map show . solve . map read .tail . words
75
67
40
33