I want to make a function that given the name of a person deletes all entries in the phone book with that name.
type Name = String
type PhoneNumber = Int
type Person = (Name, PhoneNumber)
type PhoneBook = [Person]
delete::Name -> PhoneBook -> PhoneBook
how would go about this
would I use drop
I've been using this but I've been getting error
delete :: Name -> PhoneBook -> PhoneBook
delete name = (drop name xs)
Problem
First of all, if you're trying to delete one specific element from a list in Haskell you're usually doing something wrong. There are better types to do this, fromData.Map in this case to Data.Ord in many others.
However, if you want to do it your way, drop is not the function for it. If you look at its type, drop :: Int -> [a] -> [a] you'll realise it only drops the first n elements.
Solution
You can however use a higher order function, filter :: (a -> Bool) -> [a] -> [a] which does what it says on the tin. Just need to give it a function to filter what you need. You can use a lambda function with an easy pattern matching:
deletePerson :: Name -> [PhoneBook] -> [PhoneBook]
deletePerson na = filter (\(n, p) -> name /= n)
Also note that delete is a function in Data.List that deletes the first occurrence of something in a list
I'm getting a match type [Char] with String -> Bool error:
isPalindrome :: String -> Bool
isPalindrome w = w == reverse w
countPalindromes :: [String] -> Int
countPalindromes ss = length (filter (== isPalindrome) ss)
countPalindromes uses isPalindrome to check if a string is a palindrome.
I now have a different issue than in my first question about this palindrome count task. The first issue was solved, and I was instructed to open a new question to solve the new issue. Which is why this is a different question.
isPalindrome :: String -> Bool, which is to say that it expects a string, then gives you a boolean to say whether or not that string is a palindrome.
(==) :: Eq a => a -> a -> Bool, which is to say that it expects two values of typeclass Eq (in other words: anything equatable) and tells you whether or not they are equal.
Pair those together and you get (== isPalindrome) :: (String -> Bool) -> Bool*. You've handed (==) a String -> Bool value, so it's expecting one more and will tell you if the two are equal. That's not quite what you want, though. You're not comparing two functions....
In fact, you're not comparing any two things at all. You only want to see which values passed to countPalindromes return True when called by isPalindrome. That's what filter is for!
filter :: (a -> Bool) -> [a] -> [a]
It's looking for an a -> Bool to pass as the first argument. This is the function that will be deciding what makes it through the filter and what doesn't, and in this case you want to use some derivation of isPalindrome. Looking again at isPalindrome in this context we see:
isPalindrome :: String -> Bool
that looks an awful lot like an a -> Bool function! Let's try substituting all the as in filter's type signature with String.
filter :: (String -> Bool) -> [String] -> [String]
That looks like it's exactly what you're wanting! Try, then, using filter isPalindrome instead of filter (== isPalindrome).
* nitpick: functions (more generally: values of type (-> r)) are not members of the Eq typeclass so you'd actually get an error saying that you can't tell if a String -> Bool is equal to another String -> Bool. It's not relevant to the problem at-hand, though, so I'm pretending that's not an issue and burying this explanation down here.
How can I search a tuple based on the first element or second or third?
I know how to search tuple of two but how do i do it for more than two?
type Stuff = (String, String, Int)
testStuff :: [Stuff]
testStuff = [
("beans","black",5),
("cod","fish",4),
("coke","diet",3)
]
How can I write a function that will search "Stuff" and return the "int" value?
e.g searchStuff "beans" should return 5.
Since you haven't provided your function for searching in a list of pairs, I'm going to assume that you used lookup. Lets focus on find for your new function. find can be found in Data.List (and a more general version in Data.Foldable) and has the following type:
find :: (a -> Bool) -> [a] -> Maybe a
Now, if you need to find something in a list of triples based on the first element, you could use
find (\(a,_,_) -> a == "beans") testStuff
However, this will leave you with a Maybe Stuff. But since Maybe is an instance of Functor, it is easy to change the result to Maybe Int (and is left as an exercise).
The Prelude defines lookup to handle searching a list of pairs. Here's the definition:
-- | 'lookup' #key assocs# looks up a key in an association list.
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup _key [] = Nothing
lookup key ((x,y):xys)
| key == x = Just y
| otherwise = lookup key xys
Can you see how one would define a similar function to search a list of triples?
This question is about type in Haskell programming language.
When I type
:t []
I get the return as:
[] :: [a]
What is [a]?
Rewriting it like so might make things clearer:
[] :: forall a. [a]
So, since it doesn't contain any value, haskell can't decide on a type and leaves it open. If you use it in a typed expression, however, like
x = []
f :: [Int] -> [Int]
f l = l
y = f x
it automatically gets resolved to [Int], since it is used as this type.
It's a placeholder. It basically means any type could go there. In other words, if you had a function
someFunc :: [Int] -> ()
You could pass [] to it because [] is [a], which will match [Int] (by replacing the a placeholder with the concrete Int type).
Now if you look at, say, id, you'll find it has the type a -> a. This means that it's a function that takes an object of any type, and returns an object of the same type. Interestingly, because the function knows absolutely nothing about the object it's given (since it has no constraints on the type), you know that this function has to do either of two things:
Return the input object, or
Return ⊥ (bottom).
I'm trying to write a simple program in Haskell that can determine someone's body mass index.
Here's what I have written:
type Height = Float
type Weight = Float
type PeopleStats = [(String, Height, Weight)]
and...
bmi :: Height -> Weight -> Float
bmi heightCm weightKg = weightKg/(heightCm)^2
healthy :: Height -> Weight -> Bool
healthy heightCm weightKg | 25 > index && 18 < index = True
| otherwise = False
where index = bmi heightCm weightKg
So far, the function "healthy" can calculate someone's BMI, and the function "healthyPeople" returns a boolean statement determining if the person's BMI falls within the limits which is considered normal for a healthy person.
I want to write a function called "healthyPeople".
healthyPeople :: PeopleStats -> [String]
This function needs to take a list of PeopleStats and returns a list of names (Strings) of people who are deemed to be "healthy" from the "healthy" function.
For example:
If I input [("Lee", 65, 185), ("Wang", 170, 100), ("Tsu", 160, 120)] I will get a list of the names of the people whose BMI returns true form the boolean function in "healthy".
Please help !!!!
First, I think you probably meant to define bmi as:
bmi :: Height -> Weight -> Float
bmi heightCm weightKg = weightKg/(heightCm/100)^2
since the formula uses height in meters.
Now, here's a step by step way to do it using helper functions. I defined a type:
type PersonStats = (String, Height, Weight)
and some functions on that type:
healthyPerson :: PersonStats -> Bool
healthyPerson (name, h, w) = healthy h w
getName :: PersonStats -> String
getName (name, h, w) = name
With those in place, the final function becomes trivial:
healthyPeople :: PeopleStats -> [String]
healthyPeople people = map getName $ filter healthyPerson people
or in point-free notation:
healthyPeople :: PeopleStats -> [String]
healthyPeople = map getName . filter healthyPerson
First you filter out the healthy people from the list, then you map the list of stats into a list of names.
You can express the entire function in one go without the helpers if you use lambdas.
There's a standard Haskell function named filter that does exactly (well, almost) what you want here. It has type (a -> Bool) -> [a] -> [a], i.e., it takes a predicate and a list and returns the members that satisfy the predicate.
You can't apply it directly to PeopleStats because the types don't match up, but it's not hard to write a function to connect the two:
healthyPerson :: (String, Height, Weight) -> Bool
healthyPerson (_, h, w) = healthy h w
healthyPeople :: [(String, Height, Weight)] -> [String]
healthyPeople people = map name $ filter healthyPerson people
where name (s, _, _) = s
This does what you want.
Let's think about what you want to do. You have a list, and you want to (a) select only certain items from the list, and (b) do something to each element of the list. This being Haskell, let's express this in types. The first thing you need—well, it'll have to take a list [a], and a way to check if each element is good. How can it check? Well, it should be a function a -> Bool. And it should give us back a smaller list. In other words, something like [a] -> (a -> Bool) -> [a]. Then we want to take our list and do something to each element. In other words, we'll need a list [a], and a function a -> b. Thus, we'll want something of the type [a] -> (a -> b) -> [b]. Now that we have the types, we're golden: we can use Hoogle to search for them. I highly, highly recommend using Hoogle regularly; it's a Haskell search engine which searches both types—the uniquely awesome part—and function/datatype/typeclass/module/package names. The first function, as it turns out, is the second result for the query: filter :: (a -> Bool) -> [a] -> [a]. This takes a function and a list and returns only the elements of the list for which the function is true. The second function is the first result, map :: (a -> b) -> [a] -> [b], which calls the given function on every element of the given list and returns a list of the results. Note that the arguments have the function, not the list, first; this is more natural, as you'll see shortly.
We want to put these two together for healthyPeople:
healthyPeople :: PeopleStats -> [String]
healthyPeople sts = map (\(n,_,_) -> n) $ filter (\(_,h,w) -> healthy h w) sts
This does what you want. $ is function application, but effectively groups the right-hand side because of its precedence; this allows us to elide parentheses. Here we see why it's nice to have map take its function first; we pass it the name-extracting function ((n,_,_) is a pattern which will match a triple and assign n its first element, ignoring the other two), and then (via $) the filtered list.
This is nice, but not how I'd actually write it. Since sts is the last parameter to the function and to its body, it's unnecessary. In truth, all functions in Haskell take only one argument; this means that if you don't pass enough arguments, you get a function which expects the missing arguments and returns the result. With the help of the function-composition operator ., this gives us
healthyPeople :: PeopleStats -> [String]
healthyPeople = map (\(n,_,_) -> n) . filter (\(_,h,w) -> healthy h w)
And that's probably how I'd write it! You'll find yourself using map and filter a lot; they're real workhorses in functional programming.
There is another idiomatic way you can write healthyPeople; you can use a list comprehension, as follows:
healthyPeople :: PeopleStats -> [String]
healthyPeople stats = [n | (n,h,w) <- stats, healthy h w]
This reads as "construct the list of every n such that (n,h,w) is an element of stats and healthy h w is true. If any of the pattern matches or the predicates fail (you can have more than one of each, though you don't need that here), that element is skipped; otherwise, the left side of the | is executed. It's effectively another way of writing the map/filter version.
Edit 1: As many others are saying, your units are off in bmi; you should have heightCm/100. Also, your healthy function has code equivalent to
f x | cond = True
| otherwise = False
This is equivalent to writing, in a C-like,
bool f(some_type x) {
if (cond)
return true;
else
return false;
}
Instead, you should just write
bool f(some_type x) {
return cond;
}
Or, in this case
f x = cond
This gives you the shorter code
healthy :: Height -> Weight -> Bool
healthy heightCm weightKg = let index = bmi heightCm weightKg
in 25 > index && 18 < index
(You can use a where clause too, but here's a let just because I like it better :))
First off, note that your definition of BMI is incorrect - you need to convert centimetres into metres:
bmi heightCm weightKg = weightKg/(heightCm/100)^2
With that fixed, I came up with the following:
healthyPeople :: PeopleStats -> [String]
healthyPeople [] = []
healthyPeople ((name, height, weight):xs) | healthy height weight = name : healthyPeople xs
| otherwise = healthyPeople xs
This is fairly straight forward. It uses list-based recursion to recurse over all the elements of the list, and it uses guards similarly to how you used them in the healthy function to switch behaviour based on whether the person at the head of the list is healty or not. If they are healthy, their name is concatted with the result of processing the rest of the list.
Next time, you should try solving the problem yourself and then ask for help (and show what you've tried). You'll learn far more!
type Height = Float
type Weight = Float
data PersonStats = PersonStats
{ personName :: String, personHeight :: Height, personWeight :: Weight }
bmi :: Height -> Weight -> Float
bmi heightCm weightKg = weightKg/(heightCm / 100)^2
healthy :: Height -> Weight -> Bool
healthy heightCm weightKg = 25 > index && 18 < index
where index = bmi heightCm weightKg
healthyPerson :: PersonStats -> Bool
healthyPerson p = healthy (personHeight p) (personWeight p)
healthyPeople :: [PersonStats] -> [String]
healthyPeople = map personName . filter healthyPerson