Reputation:
My goal is a create calculator which takes in times either in 12 or 24-hour format and tells the user, what activity to do. #:## am and ##:## am #:## pm and ##:## pm
I am getting this error TypeError: '>=' not supported between instances of 'NoneType' and 'float'
is x not a string when I compare it and then get converted to a float after that?
This is my code
def main():
time = input("What time is it? ")
if eat(time)>=7.0 and eat(time)<=8.0:
print("Breakfast")
elif 0.0>=eat(time)<=1.0:
print("Lunch")
elif 6.0 >=eat(time)<=7.0:
print("Dinner")
def eat(x):
# remove .am and .pm
if x == x.endswith("am"):
x = x.replace("am","")
hours, minutes= x.split(":")
x = (float(hours)+float(minutes)/60)
return x
elif x == x.endswith("pm"):
x = x.replace("pm","")
hours, minutes= x.split(":")
x = (float(hours)+float(minutes)/60)
return x
main()
Upvotes: 0
Views: 242
Reputation: 20873
Split your task into subtasks:
Create a high-order function in Haskell that takes in another function.
higherOrder :: (a -> b) -> Bool
higherOrder f = undefined -- a higher order function that takes
-- in another function
We have not learned anything about the type of the passed function, which is why we use the placeholder a -> b
. This will be change later, once we learn more about f
.
That second function takes in a list and evaluates to each index to be true or false.
This function is passed in. You don't need to implement it, it will be provided as an argument. You do however need to know its type signature, in this case
f :: [a] -> [Bool] -- a function taking a list of any type
-- ([a]), evaluating it to a list of booleans
-- example usage
f [1, 2, 3] == [True, False, True]
Which we use to update the type of our higherOrder
higherOrder :: ([a] -> [Bool]) -> Bool
The high order function should evaluate to true if the second function evaluates to true for at least 2 indexes in the list
You could replace this step with a simpler step: Write a function atLeastTwo :: [Bool] -> Bool
, that takes a list of Booleans ([Bool]
) and returns True
if at least two indexes' values are true.
atLeastTwo :: [Bool] -> Bool
atLeastTwo xs = undefined
Maybe you can implement atLeastTwo
by filtering the list, keeping only True
values and then counting its length. You might find filter :: (a -> [Bool]) -> [a] -> [a]
and length :: [a] -> Int
1 useful.
Putting it all together you will discover that the task description is not clear. It does not talk about the list that is passed to higherOrder
. In your case it probably should have been passed as a second parameter (xs
) so we update higherOrder
again to
higherOrder :: ([a] -> [Bool]) -> [a] -> Bool
higherOrder f xs = undefined
A more natural problem would be, where the passed function processes a list element (a -> Bool
) instead of a list ( [a] -> [Bool]
), and would read:
[Updated/alternative assignment: replacing
([a] -> [Bool])
with(a -> Bool)
.]Implement a (higher-order) function
atLeastTwoTrues :: (a -> Bool) -> [a] -> Bool
. The first argument being passed toatLeastTwoTrues
should be a function that can evaluate a value to eitherTrue
orFalse
. The second argument is a list of values. Your function should returnTrue
if and only if at least two elements of the passed list evaluate toTrue
using the first argument.
This would avoid some ambiguity but is a different problem.
Good luck and enjoy your Haskell journey. It is difficult at the start. It has been for all of us. Don't give up, because once you start to master it, you will enjoy it.
1This is actually not the complete truth since length
works with more data types than just lists and has a more general type.
Prelude> :t length
length :: Foldable t => t a -> Int
Upvotes: 4