Monday, June 24, 2013

[kiwzoxbe] Deep maybe

Given a Haskell record data type, transform it so that each of its fields becomes a Maybe type, and do this recursively into subrecords, including the top level.

data Foo = Foo Int String ; data Bar = Bar Foo Float

data FooM = FooM (Maybe Int) (Maybe String) ; type MFoo = Maybe FooM ; data BarM = BarM MFoo (Maybe Float) ; type MBar = Maybe BarM

Next, transform a function that operates on the original non-Maybe type to work on the new type, inserting Nothing when there is missing needed data.  This is very similar to liftM except deep.  Simple example:

f :: (Foo -> Bar) -> (MFoo -> MBar)

This has some feel of reifying laziness: where Foo had a bottom value, MFoo can have a Nothing.

Given a Nothing in one of the fields of the output, get a trace of which operation in the function, and which Nothing in the input, caused it.

Generalize to any MonadPlus.

Avoid confusion between Maybes inserted by this transformation and Maybes that which were present in the original data type.  Perhaps it should be a different Maybe.

Somewhat inspired by databases which permit "undefined" in any field.

No actual application in mind for this, yet.

1 comment:

Luke Palmer said...

Or recurse through an arbitrary functor:

data FooM f = FooM (f Int) (f String)

etc.

Functions manipulating FooM will require different features of this functor: Applicative, Monad, MonadPlus (as you say).

The trace can be done via tagging: using the functor Either Tag.

This is essentially having the datatype live in a Kleisli category. It'd be cool to be able to have category-polymorphic datatypes.