Error when using RecordWildCards extension from GHCi - haskell

I have created a function that uses the RecordWildCards syntax for pattern matching on a Haskell record type:
Pragmas
I have placed the pragmas at the top of the file. I have also tried adding it with :set -XRecordWildCards.
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
Type definitions
data ClientR = GovOrgR { clientRName :: String }
| CompanyR { clientRName :: String,
companyId :: Integer,
person :: PersonR,
duty :: String
}
| IndividualR { person :: PersonR }
deriving Show
data PersonR = PersonR {
firstName :: String,
lastName :: String
} deriving Show
Function
greet2 :: ClientR -> String
greet2 IndividualR { person = PersonR { .. } } = "hi" ++ firstName ++ " " ++ lastName + " "
greet2 CompanyR { .. } = "hello " ++ firstName ++ " " ++ lastName ++ "who works as a " ++ duty ++ " " ++ clientRName + " "
greet2 GovOrgR {} = "Welcome"
Error
• Couldn't match expected type ‘[Char]’
with actual type ‘PersonR -> String’
• Probable cause: ‘lastName’ is applied to too few arguments
In the first argument of ‘(++)’, namely ‘lastName’
In the second argument of ‘(++)’, namely
‘lastName ++ "who works as a " ++ duty ++ " " ++ clientRName + " "’
In the second argument of ‘(++)’, namely
‘" "
++
lastName ++ "who works as a " ++ duty ++ " " ++ clientRName + " "’
Failed, modules loaded: none.
When I use this function on CompanyR to match the PersonR using as pattern, I get:
Function
greet2 c#(CompanyR { .. }) = "hello " ++ (firstName $ person c) ++ " " ++ (lastName $ person c)
Error
Couldn't match expected type ‘ClientR -> PersonR’
with actual type ‘PersonR’
• The function ‘person’ is applied to one argument,
but its type ‘PersonR’ has none
In the second argument of ‘($)’, namely ‘person c’
In the first argument of ‘(++)’, namely ‘(firstName $ person c)’
• Couldn't match expected type ‘ClientR -> PersonR’
with actual type ‘PersonR’
• The function ‘person’ is applied to one argument,
but its type ‘PersonR’ has none
In the second argument of ‘($)’, namely ‘person c’
In the second argument of ‘(++)’, namely ‘(lastName $ person c)’

You do it right in your first case here (although I fixed a ++ where you had +):
greet2 :: ClientR -> String
greet2 IndividualR { person = PersonR { .. } } = "hi" ++ firstName ++ " " ++ lastName ++ " "
But here firstName etc are not records in CompanyR so CompanyR { .. } does not bring them into scope:
greet2 CompanyR { .. } = "hello " ++ firstName ++ " " ++ lastName ++ "who works as a " ++ duty ++ " " ++ clientRName + " "
You have to do something like you did in the first case of greet2, just above:
greet2 CompanyR {person = PersonR { .. }, .. } = "hello " ++ firstName ++ " " ++ lastName ++ "who works as a " ++ duty ++ " " ++ clientRName ++ " "

Related

Why am I getting problems with pattern matching?

I am getting a parse error in my code and I don't know why. I can't see any problems with the code as it's the same syntax as pattern matching I have used in the past.
My code:
transaction_to_string (sob : unit : price : stock : day) :: Transaction
| sob == 'S' = "Sold " ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
| sob == 'B' = "Bought " ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
Where Transaction is a custom data type - Transaction = (Char, Int, Int, String, Int)
Error:
Parse error in pattern: transaction_to_string
|
23 | transaction_to_string (sob : unit : price : stock : day) :: Transaction
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are several syntax errors in your code example.
try this instead:
type Transaction = (Char, Int, Int, String, Int)
transaction_to_string :: Transaction -> String
transaction_to_string (sob, unit, price, stock, day)
| sob == 'S' = "Sold" ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)
| sob == 'B' = "Bought " ++ (show unit) ++ " units of " ++ (show stock) ++ " for " ++ (show price) ++ " pounds each on day " ++ (show day)

Function expects Char in place of [Char]

I am new to Haskell and functional programming, and can't understand why this function cannot identify the correct type:
mformat :: [Char] -> [Char] -> [Char]
mformat first last = ((formatted first last) ++ " " ++ first ++ " " ++ last ++ ".")
where formatted (f:_) (l:_) = (f ++ "." ++ l ++ ".")
which causes the error:
teststuff.hs:42:40: error:
* Couldn't match type `Char' with `[Char]'
Expected: [[Char]]
Actual: [Char]
* In the second argument of `formatted', namely `last'
In the first argument of `(++)', namely `(formatted first last)'
In the expression:
(formatted first last) ++ " " ++ first ++ " " ++ last ++ "."
|
42 | mformat first last = ((formatted first last) ++ " " ++ first ++ " " ++ last ++ ".")
| ^^^^
Failed, no modules loaded.
I don't understand what is wrong here, any help would be appreciated.
The issue is in your formatted function. You are pattern matching on a String, you get Chars (f & l) and then you try concatenating them with a String. You cannot concatenate a Char with a String ([Char]).
mformat :: String -> String -> String
mformat first last = ((formatted first last) ++ " " ++ first ++ " " ++ last ++ ".")
where
formatted :: String -> String -> String
formatted (f:_) (l:_) = ([f] ++ "." ++ [l] ++ ".")
or
-- ...
formatted (f:_) (l:_) = (f : "." ++ l : ".")
The type checker thinks thinks that f and l in your case must be lists - because you are attempting to concatenate them. Then it infers (via pattern matching) from the list constructor, that first and last are lists of Strings i.e. [String] or [[Char]].

Add a typeclass constraint on a Record type

Before this declaration was working well in my context :
data PersistedCommand = PersistedCommand { offset :: Offset , command :: Command }
instance Show PersistedCommand where
show persistedCommand = "PersistedCommand { offset = " ++ ( show $ offset persistedCommand) ++ " , command = " ++ (show $ getCommandName $ command persistedCommand) ++ ":"
++ (show $ getAggregateId $ command persistedCommand) ++ " }"
But I've changed Command from a data type to a type class. How do I express this now in the previous declaration ?

Combining Maybe, IO and functions outside context result in error

Can't figure out how to make code below work. Tried all possible typesigs I think.
Code
type SerialNumber = (String, Int)
serialList :: Map.Map String SerialNumber
serialList = Map.fromList [("belt drive",("BD",0001))
,("chain drive",("CD",0002))
,("drive pulley",("DP",0003))
,("drive sprocket",("DS",0004))
]
findSerial :: Ord k => k -> Map.Map k a -> Maybe a
findSerial input = Map.lookup input
outOfContext (Just (a, b)) = (a, b)
getSerialFromUser :: IO ()
getSerialFromUser = do
putStr "Lookup part: "
input <- getLine
let output = findSerial input serialList
putStrLn "\nFound entry: " ++ output
Error
• Couldn't match expected type ‘[()]’
with actual type ‘Maybe SerialNumber’
• In the second argument of ‘(++)’, namely ‘output’
In a stmt of a 'do' block: putStrLn "\nFound entry: " ++ output
In the expression:
do putStr "Lookup part: "
input <- getLine
let output = findSerial input serialList
putStrLn "\nFound entry: " ++ output
|
62 | putStrLn "\nFound entry: " ++ output
Trying my first steps in Haskell without the books so please be gentle.
In Haskell function application is left associative, which means the expression:
putStrLn "\nFound entry: " ++ output
is parsed as
(putStrLn "\nFound entry: ") ++ output
But you probably expected it to be parsed as:
putStrLn ("\nFound entry: " ++ output)
That's why you need either to specify the parentheses explicitly or use $ operator:
putStrLn $ "\nFound entry: " ++ output
But notice, that output is of SerialNumber type, but (++) takes two lists as an argument. Therefore, you need to revise, which behaviour you want to specify to your program.

Rvar to String when randomizing list comprehension

Hey so im trying to pick a random element from this list of list Strings however when i try to add choice to the list comprehension ...
{-# LANGUAGE UnicodeSyntax #-}
import System.Random(randomRIO)
import Data.Random.Extras(choice)
import Data.Char (digitToInt)
...
getConclusion :: String -> String -> [String]
getConclusion operators atoms =
choice [[atom1] ++ " " ++ [operator] ++ " " ++ [atom2] | atom1 <- atoms, atom2 <- atoms, operator <- operators]
... I get this error:
/home/joe/Documents/haskell/LAG/main/main.hs: line 56, column 4:
Couldn't match type `Data.RVar.RVarT
Data.Functor.Identity.Identity [Char]'
with `[String]'
Expected type: [String]
Actual type: Data.RVar.RVar [Char]
In the return type of a call of `choice'
In the expression:
choice
[[atom1] ++ " " ++ [operator] ++ " " ++ [atom2] |
atom1 <- atoms, atom2 <- atoms, operator <- operators]
In an equation for `getConclusion':
getConclusion operators atoms
= choice
[[atom1] ++ " " ++ [operator] ++ " " ++ [atom2] |
atom1 <- atoms, atom2 <- atoms, operator <- operators]
Take a look at the type of choice :: [a] -> RVar a. Your function should have the type String -> String -> RVar String. The RVarT Data.Functor.Identity.Identity [Char] is just a long synonym for RVar String.

Resources