laureen
laureen

Reputation: 11

Accessing my own type (data type) inside my own type (data type2) in Haskell?

Alright so I have two types:

data Ingredient = Ingredient { potato :: String, amount :: Int, cookingTime :: Int }

data Soup = Soup { availableTime :: Int, recipe :: [Ingredient], shoppingList :: [Ingredient], canBeDone :: Bool  }

now if I want to compare the "available Time" and the "cookingTime" of an Ingredient (basically if I have enough time to cook that ingredient if I only have "availableTime" to cook the whole soup). And if I can cook the Ingredient in my soup, the Ingredient gets shifted into the shoppingList list. How do I go about that? Here's what I came up with:

doIHaveTime :: Soup -> Soup
doIHaveTime Soup{availableTime = a, recipe = [Ingredient{cookingTime = b}] } = if a >= b then Soup{ shoppingList = b:xs } else show "Can't be done."

does that way of thinking make sense? These are the errors I get:

soupExample.hs:6:128: error: • Couldn't match type ‘[Char]’ with ‘Soup’ Expected type: Soup Actual type: String • In the expression: show "Can't be done." In the expression: if a >= b then Soup {shoppingList = b : xs} else show "Can't be done." In an equation for ‘doIHaveTime’: doIHaveTime (Soup {availableTime = a, recipe = [Ingredient {cookingTime = b}]}) = if a >= b then Soup {shoppingList = b : xs} else show "Can't be done." Failed, modules loaded: none.

Upvotes: 1

Views: 97

Answers (1)

Erich
Erich

Reputation: 1848

To handle multiple ingredients in a soup you can use all :: (a -> Bool) -> [a] -> Bool to check if every ingredient in the recipe can be cooked in the available time:

enoughTime = all ((>=available) . cookingTime) ingredients

Then you have to return a Soup in both if and else branches. In total this can look like this:

doIHaveTime :: Soup -> Soup
doIHaveTime soup@Soup{ availableTime = available, recipe = ingredients }
    = if enoughTime
        -- add ingredients to shoppingList and set canBeDone to True
        then soup { shoppingList = ingredients
                  , canBeDone = True }
        -- clear shoppingList and set canBeDone to False
        else soup { shoppingList = []
                  , canBeDone = False }
  where enoughTime = all ((>=available) . cookingTime) ingredients

Note that I used soup@Soup{ ... } to pattern match and store the value at the same time in the variable soup. That way you only have to modify the two fields shoppingList and canBeDone.

Upvotes: 1

Related Questions