I want to understand Haskell better by trying to stretch possibilities of Functor, Applicative, and Monad as much as possible and study how they behave. So in [*Learn You a Haskell*](http://learnyouahaskell.com/a-fistful-of-monads) there's an exercise to generate all possible moves for a knight from a given position on chessboard:

    moveKnight :: KnightPos -> [KnightPos]  
    moveKnight (c,r) = filter onBoard  
        [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)  
        ,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)  
        ]  
        where onBoard (c,r) = c `elem` [1..8] && r `elem` [1..8] 

Now I thought to myself, wait a second, I can actually generate that list `[(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1),(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)]` instead of hardcoding it. So this is how I did it with list comprehensions:

    invert x
      | x == 1 = 2
      | x == 2 = 1
      | otherwise = 0
    
    moves = [(c `f` a, r `g` (invert a)) |
             c <- [6],
             r <- [2],
             f <- [(+), (-)],
             g <- [(+), (-)],
             a <- [1, 2]]

    -- generates: [(7,4),(8,3),(7,0),(8,1),(5,4),(4,3),(5,0),(4,1)]

With applicative approach I don't know how to do it. The below code generates 2 times more elements, because it doesn't know, that if you increment/decrement by 1 on the left side, you must do it by 2 on the right side:

    [(,)] <*> ([(+), (-)] <*> [6] <*> [1, 2]) <*> ([(+), (-)] <*> [6] <*> [1, 2])
    -- generates: [(7,7),(7,8),(7,5),(7,4),(8,7),(8,8),(8,5),(8,4),
    --             (5,7),(5,8),(5,5),(5,4),(4,7),(4,8),(4,5),(4,4)]

My questions are:

- How to implement the generation of such list with applicative style?
- How to generalize it to arbitrary possible permutations?
- What intuitions, insights and lessons can I get from this exercise?

I know that this is a massively contrived situation, but they serve me as an exercise to understand language better.