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
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)
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]].
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 ?
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.
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.