Question
Define the type constructor F
in Haskell like this:
data BTree a = Leaf a | Branch (BTree a) (BTree a)
data F a = F (Maybe (BTree a))
The type constructor F
is polynomial, so it is a Functor
, an Applicative
, a Traversable
, but not obviously a Monad
.
Can we implement bind
and return
for F
that satisfy the monad laws and thus make F
into a monad? Or is that impossible?
Motivation
The question is motivated by the fact that F
is a generator of data structures of a special kind. Namely, certain F
-algebras are monoids that may violate the associativity law. More rigorously, the type F t
is an initial object in the category of not-quite-monoids generated by type t
that may violate the associativity law.
To see why:
First, we can define the monoid-like operations on F a
. The empty element is F Nothing
and the binary operation puts two values into the branches of a tree unless one of the values is empty.
Second, suppose the type T
is an F
-algebra, so we have h: F T -> T
. This means we have h(F Nothing)
, which is a value of type T
that serves as the empty value of the monoid, and we have a binary operation (T, T) -> T
defined by \(x,y) -> h(F(Just(Branch(Leaf x) (Leaf y))))
. Further, suppose that h
preserves the monoid operations, then h
will also preserve the identity laws. So, T
is a not-quite-monoid that satisfies the identity laws (but may violate the associativity law).
F
looks like the tree monad BTree(Maybe a)
factored by the identity laws of a monoid, although I don't have a formal way of deriving F
from that.
The usual folklore knowledge is that F
-algebras with laws need to be described via monad algebras. But if F
is not a monad then that is not true. The typeclass laws need to be described in a more general way.
But the main question is: can we make F
into a monad?