[Haskell-cafe] Comonadic composition and the game "Doublets"

Ryan Ingram ryani.spam at gmail.com
Mon Jun 8 18:21:41 EDT 2009


You can write this in terms of comonads if you have this additional function:

] focus :: (Container w) => (a -> a) -> (w a -> w a)

with the idea that "focus" modifies the current "point" of the comonad
(the thing returned by extract) while leaving the rest alone.

] focus f w = something (f $ extract w)

For lists, this is easy:

> focus f (x:xs) = f x : xs

Then we can use comonadic "extend" to build the sublists:

> each :: (a -> a) -> [a] -> [[a]]
> each = extend . focus

However, I think each element of the result might be "focused" on the
wrong target; we may need to be able to re-focus the lists at the
beginning.  (I haven't tested this code...)

  -- ryan

On Mon, Jun 8, 2009 at 12:24 PM, Matthew<adnorm at gmail.com> wrote:
> Today, I was working on coding a solver for the game "doublets".
> It's a word game where you transform the start word into the end
> word one letter at a time (and the intermediate states must also
> be valid words).  For example, one solution to ("warm", "cold") is
>
>        ["warm", "ward", "card", "cord", "cold"]
>
> So, one of my first goals was to write a function that would generate
> the possible words a given word could transition to.  Here's a simple
> recursive implementation:
>
>        transition :: [Char] -> [[Char]]
>        transition [] = []
>        transition (c:cs) = map (c:) (transition cs) ++ map (:cs) ['a'..'z']
>
> For some reason, I find this formulation to be strangely unsatisfying.
> It seems to me that this sort of computation -- i.e. modifying each
> element of a container (but only one at a time) -- should be
> expressible with some higher order function.  In a nutshell, what I'm
> looking for would be a function, say "each" with this type.
>
>        each :: (Container c) => (a -> a) -> c a -> c (c a)
>
> I'm not particularly sure what Class to substitute for "Container".
> Comonad seemed like a promising solution initially, and provides
> the basis for my current implementation of the "doublets" solver.
>
> The problem being that cobind (extend) takes a function of type (w a -> a)
> instead of (a -> a).  I suspect that there may be a clever way to write
> "each" by using liftW in combination with .>>  or something like that,
> but presently, I'm at a loss.
>
> Has anyone else encountered this sort of abstraction before.  I'd love
> to hear your ideas about what Classes "each" should support, and
> how to implement it.
>
>
> Matt
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>


More information about the Haskell-Cafe mailing list