[Haskell-cafe] Replace data constructors via meta programming

Sergey Vinokurov serg.foo at gmail.com
Mon Feb 12 09:34:09 UTC 2018


Hi Vilem,

One possible solution here is to define a fold  function that captures
the relationship between constructors and functions to substitute
instead (please see the Logic.hs attachment). But it may be a bit
error-prone to use because the relationship is captured implicitly by
corresponding argument of the 'foldProposition' function.

Another approach with a bit more upfront boilerplate, but hopefully less
code later, would be recursion schemes. Please refer to
LogicRecSchemes.hs for a sample. In order to learn more you can either
read
https://github.com/willtim/recursion-schemes/raw/master/slides-final.pdf
or https://github.com/sergv/kievfprog-2017-november/blob/master/Talk.pdf
or listen to any recent talk on the topic.

Regards,
Sergey

On 02/12/2018 02:30 AM, Vilem-Benjamin Liepelt wrote:
> Hi,
> 
> I am looking for a solution to get rid of this silly boilerplate:
> 
> eval :: Ord var => Map var Bool -> Proposition var -> Bool
> eval ctx prop = evalP $ fmap (ctx Map.!) prop
>   where
>     evalP = \case
>         Var b -> b
>         Not q -> not $ evalP q
>         And p q -> evalP p && evalP q
>         Or p q -> evalP p || evalP q
>         If p q -> evalP p ==> evalP q
>         Iff p q -> evalP p == evalP q
> 
> What I would like to do in essence is to replace the data constructors
> like so:
> 
> -- Not valid Haskell!! Can't pattern match on constructor only...
> magic = \case
>     Var -> id
>     Not -> not
>     And -> (&&)
>     Or -> (||)
>     If -> (==>)
>     Iff -> (==)
> 
> compile = transformAST magic $ fmap (\case 'P' -> False; 'Q' -> True)
> 
>>>> compile (Iff (Not (And (Var 'P') (Var 'Q'))) (Or (Not (Var 'P'))
> (Not (Var 'Q'))))
>             ((==) (not ((&&) (id True) (id False))) ((||) (not (id
> True)) (not (id False))))
> 
> Note how the compiled expression exactly mirrors the AST, so there
> should be some meta programming technique for this.
> 
> Does anyone have an idea how I can achieve this?
> 
> The full source code is here:
> https://gist.github.com/vimuel/7dcb8a9f1d2b7b72f020d66ec4157d7b
> 
> I am happy to take any other comments relating to my code...
> 
> Best,
> 
> Vilem
> 
> 
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: Logic.hs
Type: text/x-haskell
Size: 1415 bytes
Desc: not available
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20180212/51c062af/attachment.hs>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: LogicRecSchemes.hs
Type: text/x-haskell
Size: 1691 bytes
Desc: not available
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20180212/51c062af/attachment-0001.hs>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: OpenPGP digital signature
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20180212/51c062af/attachment.sig>


More information about the Haskell-Cafe mailing list