I am trying to learn IO in haskell and i found it very confusing.. Went through the documentation on hackage
https://hackage.haskell.org/package/cassava under use decodebyName
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V
data Person = Person
{ name :: !String
, salary :: !Int
}
instance FromNamedRecord Person where
parseNamedRecord r = Person <$> r .: "name" <*> r .: "salary"
main :: IO ()
main = do
csvData <- BL.readFile "salaries.csv"
case decodeByName csvData of
Left err -> putStrLn err
Right (_, v) -> V.forM_ v $ \ p ->
putStrLn $ name p ++ " earns " ++ show (salary p) ++ " dollars"
I have two questions here
-
In the declaration for Person against name they have used "!String" instead of String.. why? I ran the same example with "String" and there was no difference in output. The tutorial on stack builders site also use the "!".. What am i missing here?
-
In the main function what does
putStrLn $ name p ++ " earns " ++ show (salary p) ++ " dollars"
do?
I understand that post $ \ p is an anonymous function puts a new string concatenating name from p and salary from p showing salary because it is an int..
what does p stand for? Is it a tuple, a variable? have they used p for the Person data structure?
what does the expression Right (_, v) -> V.forM_ v mean ?
>Solution :
! before a type is called a BangPattern and it causes the argument to be evaluated to weak head normal form when the data type is constructed. Informally, it decreases the amount of laziness which in some cases will improve performance.
Right (_, v) -> V.forM_ v $ \p -> ...
This part pattern matches on v which is a Vector of rows, in your case of type Person. V.forM_ is a function of type Monad m => Vector a -> (a -> m b) -> m () from the vector package. Essentially, it performs a monadic action for each element of the vector, in your case, an IO action of type Person -> IO (). So p in this case, is an individual Person.