Reputation: 23352
Here's a snippet of a Haskell program I'm trying to understand:
englishToFrench = [("the", "le"),("savage", "violent"),("work", "travail"),
("wild", "sauvage"),("chance", "occasion"),]
data Entry = Entry {word :: String,
definition :: String,
length' :: Int}
deriving Show
listOfEntries = map (\(x, y) -> Entry x y (length x)) englishToFrench
Briefly, the program takes a list of String tuples and turns out a list of Entry objects.
However, I don't like the lambda functions in the map
and I'd like to create a regular function to replace it.
I attempted this but it is giving me an error that x and y are not in the scope:
entryBuilder x y = Entry x y (length x)
entries = map (entryBuilder x y) englishToFrench
Can anyone tell me how to convert the lambda function and what the general method is?
Upvotes: 0
Views: 614
Reputation: 144206
Firstly, your entryBuilder
function has the wrong type. It should be:
entryBuilder :: (String, String) -> Entry
entryBuilder (x, y) = Entry x y (length x)
while yours has type
String -> String -> Entry
the type of map
is
map :: (a -> b) -> ([a] -> [b])
since your list type is [(String, String)] you want a function of type
(String, String) -> b
to pass to map
.
This is your entryBuilder
function, so you can just use
listOfEntries = map entryBuilder englishToFrench
Note that you can use your existing definition of entryBuilder
using uncurry
:
entryBuilder :: String -> String -> Entry
listOfEntries = map (uncurry entryBuilder) englishToFrench
uncurry
has the type
uncurry :: (a -> b -> c) -> ((a, b) -> c)
i.e. it converts a curried function in two arguments into a function with a single pair argument. Since your existing entryBuilder
function has type
String -> String -> Entry
uncurry entryBuilder
has type
(String, String) -> Entry
which is the function type you require to pass to map
.
Upvotes: 5