Skip to content

Take a Quick Look at lists

I want to make a video about Quick Look. But I also want it to have more content than just the venerable head ids. So I thought a bit about what would make a nice use case for impredicative polymorphism. I came up with the idea of using forall a. Tree a -> Maybe a as the type of indices into a tree structure. I could now search in one tree for a value that satisfies a predicate returning a forall a. Tree a -> Maybe a to then retrieve a corresponding value (if the tree has the right shape) in another tree. Here is the code:

data Tree a
  = Leaf a
  | Node (Tree a) a (Tree a)
  deriving (Show, Functor)

type TreeIndex = forall a. Tree a -> Maybe a

lookupTree :: forall a. (a -> Bool) -> Tree a -> Maybe TreeIndex
lookupTree p = go
  where
    go :: Tree a -> Maybe TreeIndex
    go (Leaf x)
      | p x = Just (\case Leaf y     -> Just y
                          Node _ y _ -> Just y)
      | otherwise = Nothing
    go (Node left x right)
      | p x = Just (\case Leaf y     -> Just y
                          Node _ y _ -> Just y)
      | otherwise = asum [go left, go right] -- (go left : go right : [])

(This doesn't work, as written, because the last line just returns the TreeIndex from the recursive call. But never mind this.)

(NB to GHC aficionados: asum is the same as GHC's firstJusts.)

What's sad is that the last line fails to type-check. However, if I remove the list argument and replace it with the commented-out cons-and-nil argument, all is well. This is because GHC doesn't take a Quick Look at lists. But it really should. And probably tuples, too.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information