[Haskell-cafe] ANN: Buster 0.99.1, a library for application orchestration that is not FRP

Felipe Lessa felipe.lessa at gmail.com
Thu Apr 2 12:58:37 EDT 2009


On Thu, Apr 02, 2009 at 11:53:00AM -0400, Jeff Heard wrote:
> and so forth to be compatible with Bus [EData a], but I think that in
> the end so many widgets will reuse the EData type that it's just as
> well to make it part of the Event rather than force the user to be
> explicit about it every time.  But if I'm generally disagreed with
> about this, I can change it -- I'm pretty neutral about it, to be
> honest.

Why not trying something like what was done with the new extensible
extensions, using typeable existencials and casts? That way you could
put any value you want and they would all be first class citizens.

Another random idea: a phantom type could be used to be explicit about
the type of event something produces or expects, something on the
lines of

> data EData a = forall b. Typeable b => EData b
>              deriving (Typeable)
>
> -- | Extract the data.
> extract :: EData a -> a
> extract (EData d) = case cast d of
>                       Just x  -> x
>                       Nothing -> error "extract: phantom didn't match"
>
> -- | Carefull extract the data, returns @Nothing@ if the phantom
> --   type doesn't match.
> extractM :: EData a -> Maybe a
> extractM (EData d) = cast d
>
> -- | Extracts any type of data from a polymorphic 'EData'.
> extractAny :: (forall a. EData a) -> Maybe b
> extractAny (EData d) = cast d
> -- Is the forall above useful to prevent mistakes or not?
>
> -- | Unsafely casts the phantom type to another one.
> unsafeCastData :: EData a -> EData b
> unsafeCastData (EData d) = EData d

Your examples would become something like

> commandLineArgsWidget :: Widget [String]
> commandLineArgsWidget = getArgs >>=
>     \args -> produce' "Environment"
>                       "CommandLineArgsWidget"
>                       "argv"
>                       Persistent
>                       args
>
> environmentWidget :: Widget String
> environmentWidget b = getEnvironment >>=
>     mapM_ (\(k,v) -> produce' "Environment" "EnvironmentWidget" k
>                                Persistent v b)
>
> progNameWidget :: Widget String
> progNameWidget b = getProgName >>=
>     \v -> produce' "Environment" "ProgramNameWidget" "ProgramName"
>                     Persistent v b

where I'm assuming that you could construct the EData inside produce'
as now that's the only constructor available.  The bus could then be
polymorphic on the phantom type.  Why use phantom types at all, then?
It at least serves for documentation purposes.  Well, it is a random
idea after all :).

--
Felipe.


More information about the Haskell-Cafe mailing list