I've seen a data type defined like the following with a corresponding Monoid instance:
data Foo where
  FooEmpty :: String -> Foo
  FooAppend :: Foo -> Foo -> Foo
-- | Create a 'Foo' with a specific 'String'.
foo :: String -> Foo
foo = FooEmpty
instance Monoid Foo where
  mempty :: Foo
  mempty = FooEmpty ""
  mappend :: Foo -> Foo -> Foo
  mappend = FooAppend
You can find the full code in a gist on Github.
This is how Foo can be used:
exampleFoo :: Foo
exampleFoo =
  (foo "hello" <> foo " reallylongstringthatislong") <>
  (foo " world" <> mempty)
exampleFoo ends up as a tree that looks like this:
FooAppend
  (FooAppend
    (FooEmpty "hello")
    (FooEmpty " reallylongstringthatislong"))
  (FooAppend
    (FooEmpty " world")
    (FooEmpty ""))
Foo can be used to turn sequences of Monoid operations (mempty and mappend) into an AST.  This AST can then be interpreted into some other Monoid.
For instance, here is a translation of Foo into a String that makes sure the string appends will happen optimally:
fooInterp :: Foo -> String
fooInterp = go ""
  where
    go :: String -> Foo -> String
    go accum (FooEmpty str) = str ++ accum
    go accum (FooAppend foo1 foo2) = go (go accum foo2) foo1
This is really nice. It is convenient that we can be sure String appends will happen in the right order.  We don't have to worry about left-associated mappends.
However, the one thing that worries me is that the Monoid instance for Foo is not a legal Monoid instance.
For instance, take the first Monoid law:
mappend mempty x = x
If we let x be FooEmpty "hello", we get the following:
mappend mempty (FooEmpty "hello") = FooEmpty "hello"
mappend (FooEmpty "") (FooEmpty "hello") = FooEmpty "hello"  -- replace mempty with its def
FooAppend (FooEmpty "") (FooEmpty "hello") = FooEmpty "hello" -- replace mappend with its def
You can see that FooAppend (FooEmpty "") (FooEmpty "hello") does not equal FooEmpty "hello".  The other Monoid laws also don't hold for similar reasons.
Haskellers are usually against non-lawful instances.  But I feel like this is a special case. We are just trying to build up a structure that can be interpreted into another Monoid.  In the case of Foo, we can make sure that the Monoid laws hold for String in the fooInterp function.
- Is it ever okay to use these types of non-lawful instances to build up an AST?
 - Are there any specific problems that need to be watched for when using these types of non-lawful instances?
 - Is there an alternative way to write code that uses something like 
Foo? Some way to enable interpretation of a monoidal structure instead of usingmappendon a type directly?