Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(emulated) Macros in Haskell?

A person on Reddit has brought this code to my attention:

main = do
  let ns = [print 1, print 2, print 3]
  sequence_ ns
  sequence_ $ reverse ns
  sequence_ $ tail ns ++ [head ns]
  head ns

What's going on here is we have an array of operations that we can do stuff with, like reverse or get its tail or head.

Awesome.

What I want to do is get into individual elements and change them for good. For example, I want to be able to do something like this:

ns !! 0

and get something like [print, 1] and then change last element to, say, 3.14 so that the function would print 3.14.

Is it at all possible in Haskell or should I just go back to LISP?

AN IMPORTANT EDIT: I sort of blundered. I understand that I will need to create a new list. Is it possible to get the arguments of a function, which is a part of a list? What I want is the ability to compose functions from their identifiers/arguments and also be able to break down a function into identifier/argument before it gets evaluated.

like image 985
mannicken Avatar asked Aug 18 '09 18:08

mannicken


2 Answers

It is a bit more complicated than in Lisp, but for metaprogramming in Haskell, you can use Template Haskell.

E.g., [|print 1|] will be translated to

return $ AppE (VarE $ mkName "print") (LitE $ IntegerL 1)

which has the type Q Exp (a quotation of an expression).

If you want to splice your own data into a quotation, [|print $(foo 3.14)|] will execute foo 3.14 at compile-time.

like image 69
Alexey Romanov Avatar answered Oct 09 '22 23:10

Alexey Romanov


Once you've applied a value to a function, there's no way to get it back. Try wrapping the function and its argument in a datatype that you can evaluate or decompose depending on your needs.

data App a b = App (a -> b) a
runApp (App a b) = a b
ns = [App print 1, App print 2, App print 3]
main = do
    sequence_ $ map runApp ns
    let ns2 = [App fun (arg^2) | App fun arg <- ns]
    sequence_ $ map runApp ns2

Outputs

1
2
3
1
4
9
like image 20
Josh Lee Avatar answered Oct 09 '22 22:10

Josh Lee