user17391478
user17391478

Reputation:

Meal Time (Conditions)

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

Answers (1)

Micha Wiedenmann
Micha Wiedenmann

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] -> Int1 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

Proposal for an updated assignment

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 to atLeastTwoTrues should be a function that can evaluate a value to either True or False. The second argument is a list of values. Your function should return True if and only if at least two elements of the passed list evaluate to True 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

Related Questions