Now this problem can be solved mathematically be manipulating the recurrence relations into a closed form, but I'll focus on the more interesting problem, memoizing.
First we can use Data.Array
(this is the lazy one)
import Data.Array as A
lattice x y = array ((0, 0), (x, y)) m ! (x, y)
where m = [(,) (x, y) (lattice' x y) | x <- [0..x], y <- [0..y]
lattice' 0 0 = 1
lattice' x 0 = lattice (x-1) 0
lattice' 0 y = lattice (y-1) 0
lattice' x y | x >= y = (lattice (x-1) y) + (lattice x (y-1))
| otherwise = (lattice y (x-1)) + (lattice (y-1) x)
Now these recurrences go through the map, but, since the map is lazy, once a map entry is evaluated, it's thunk will be mutated to be a simple value ensuring it's only ever computed once.
We can also use the wonderful memo-combinators
library.
import Data.MemoCombinators as M
lattice = memo2 M.integral M.integral lattice'
where lattice' 0 0 = 1
lattice' x 0 = lattice (x-1) 0
lattice' 0 y = lattice (y-1) 0
lattice' x y | x >= y = lattice (x-1) y + lattice x (y-1)
| otherwise = lattice y (x-1) + lattice (y-1) x