haskellglossjuicy-pixels

Pick a specific picture from a list


I have the following function:

blockToPicture :: Int -> [Picture] -> Picture
blockToPicture n [pic1,pic2,pic3] | n==0 = ...
                                  | n==1 = ...
                                  | otherwise = ...

If n==0 I want to select pic1, if n==1 I want to select pic2. Otherwise I want to select pic3. The problem is when one of the pictures doesn't load, so it doesn't appear on the list. Instead of [pic1,pic2,pic3] I have something like [Pic1,Pic3]. When the function is supposed to select a picture that isn't on the list I want it to write "X" instead. For that I'll use the function text "X" instead. The problem is that I don't know how to make it write the "X" instead of selecting the wrong picture.

Edit: I've created the following function but for some reason I'm getting the error "Variable not in scope" to the pictures.

blocoParaPicture :: Int -> [Picture] -> Picture
blocoParaPicture b l | b==0 = if elem pic1 l then pic1 else text "X"
                     | b==1 = if elem pic2 l then pic2 else text "X"
                     | otherwise = if elem pic3 l then pic3 else text "X"

Solution

  • You can't just discard a picture that doesn't load; if you tried to load 3 pictures and end up with [some_pic, some_other_pic], how do you know which one didn't load? You need a list of type [Maybe Picture], with Just pic representing a successfully loaded picture and Nothing a failure. Then your function would look like

    blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
    blockToPicture _ []          = Nothing                  -- No pictures to choose from
    blockToPicture 0 (Nothing:_) = Nothing                  -- Desired picture failed to load
    blockToPicutre 0 (x:_)       = x                        -- Found desired picture!
    blockToPicture n (_:xs)      = blockToPicture (n-1) xs  -- This isn't it; try the next one
    

    Adapting Jorge Adriano's suggestion to use lookup (which is a good one)

    import Control.Monad
    
    blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
    blockToPicture n pics = join (lookup n (zip [0..] pics))
    

    Since lookup :: a -> [(a,b)] -> Maybe b and b here is Maybe Picture, we have a scenario where lookup returns Nothing if n is too big; Just Nothing if the desired picture fails to load, and Just (Just pic) if the desired picture is found. The join function from Control.Monad reduces the Maybe (Maybe Picture) value that lookup returns to the "regular" Maybe Picture that we want.