Our
Our

Reputation: 1035

How to iterate over a list of certain data types while accessing of the the elements of that data type

On code.world/haskell (see the full code), I have the following data types

data Lattice = Lattice
  {
    latPos :: (Double, Double),
    occupied :: Bool
  }

data Ant = Ant
  {
    antPos :: Point,
    bagFilled :: Bool
  }


data World = World
  {
    ants :: Ant,
    space :: [Lattice]
  }

And, inside renderWorld function, I am creating a list of Lattices. Then, I want to iterate over this list while applying the function f like this

renderWorld :: World -> Picture
renderWorld w = foldl (<>) (translated 0 0 $ rectangle 0 0) lattices
  where
    f :: Lattice -> Picture
    f lat = do
      let pos :: (Double, Double)
          pos = (latPos lat)
      if pos == (_,5) then translated pos $ solidRectangle latticeSize latticeSize
       else translated $ pos $ rectangle latticeSize latticeSize
    lattices = map f (space w)

But for some reason, it gives me the following error

Couldn't match expected type ‘Picture’ with actual type ‘Picture -> Picture’

What am I doing wrong exactly? I couldn't figure out for the last 2 hours.

Upvotes: 0

Views: 56

Answers (1)

Li-yao Xia
Li-yao Xia

Reputation: 33429

The type of translated is:

translated :: Double -> Double -> Picture -> Picture

In particular, translated takes three arguments to produce a Picture, but you only gave it two.

translated pos $ solidRectangle latticeSize latticeSize

You are passing coordinates as a pair pos, whereas they are expected to be passed separately:

let (xpos, ypos) = latPos lat
if ... then translated xpos ypos $ solidRectangle latticeSize latticeSize

Furthermore, in the else branch there is an extra $ which changes how things are associated:

translated $ pos $ rectangle latticeSize latticeSize
-- This is `translated` applied to one argument:
translated (pos (rectangle latticSize latticeSize))

Finally in the if you have a pattern, which is invalid syntax (between if and then there should be an expression):

if pos == (_, 5) then ...
else ...

In this case since it's preferable to deconstruct the pair anyway, you can instead write

if ypos == 5 then ...
else ...

But otherwise you could also have written this using case:

case pos of      -- "if"
  (_, 5) -> ...  -- "then"
  _ -> ...       -- "else"

After fixing those errors:

  where
    f :: Lattice -> Picture
    f lat = do
      let xpos, ypos :: Double
          (xpos, ypos) = (latPos lat)
      if ypos == 5 then translated xpos ypos $ solidRectangle latticeSize latticeSize
       else translated xpos ypos $ rectangle latticeSize latticeSize
    lattices = map f (space w)

Full code: https://code.world/haskell#PS44YI3JbKZc5JWvLqGRKSA

Upvotes: 1

Related Questions