2009-08-18 7 views
15

Redditの上の人は私の注意にこのコードをもたらしています:(エミュレートされた)Haskellのマクロ?

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

ここで何が起こっているが、我々は逆のように、とのものを行うか、その尻尾や頭を取得することができます操作の配列を持っています。

驚くばかりです。

私がしたいことは、個々の要素に入り、それらを変えることです。

ns !! 0 

など何かを取得[印刷を、1]、その後、関数は3.14を印刷なるように3.14、たとえば、に最後の要素を変更します。たとえば、私はこのような何かを行うことができるようにしたいです。

ハスケルでも可能ですか、それともLISPに戻るべきですか?

重要な編集:私は一掃された。私は新しいリストを作成する必要があることを理解しています。リストの一部である関数の引数を取得することは可能ですか?私が望むのは、識別子/引数から関数を構成する能力であり、関数が評価される前に識別子/引数に関数を分解することも可能です。

+0

btw:これは実際には何のために必要ですか? – yairchu

答えて

10

Lispよりも少し複雑ですが、Haskellでのメタプログラミングの場合は、Template Haskellを使用できます。

例えば、[|print 1|]Q Exp(発現の引用)を有する

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

に変換されます。

自分のデータを引用してスプライスする場合は、[|print $(foo 3.14)|]はコンパイル時にfoo 3.14を実行します。

4

リストを変異させたいですか?あなたはlispに戻ってください;-)

値はHaskellでは不変です。 Haskell-wayは、最後の要素を除いて古いリストと等価な新しいリストを作成することです。

(そこでは、可変値とポインタをシミュレートすることができモナドを含むいくつかのトリックがありますが、それはあなたがここに欲しいものはおそらくありません。)

編集:私は、編集された質問を理解全くわからないが、あなたのことができ関数と引数を別々にデータとして扱い、後に "適用する"。

do 
    let ns = [(print, 1), (print, 2), (print, 3)] 
    sequence_ $ map (\(f,a)->f a) ns 
+1

私は質問を正しく定式化していないのではないかと心配しています。私は本当に何かを変異させたくありません。私は関数識別子/引数が評価される前にそれを読み込み、汎用関数/引数から文を作成したいと考えています。 編集されました。 – mannicken

11

値を関数に適用したら、戻す方法はありません。関数とその引数を必要に応じて評価または分解できるデータ型でラップしてみてください。

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 

出力

1 
2 
3 
1 
4 
9 
+0

btwの場合は、runAppの代わりにAppの代わりに(print、1)のようなタプルを使うことができます。 – yairchu

+0

ああ、ポイントフリー表記の喜び。それでも、私は手元のタスクに固有の名前を持つ関数を持つのが好きです –

1

などはHaskellのやり方はちょうど新しいリストを作成することであると言われてきたが、あなたは本当に

import Data.Array.IO 

seqArr_ arr = getElems arr>>=sequence_ 

main= do 
    arr <- newListArray (0,2) [print 1,print 2,print 3] :: IO (IOArray Int (IO())) 
    seqArr_ arr -- prints 1 2 3 
    writeArray arr 2 (print 3.14) -- change the last element 
    seqArr_ arr -- prints 1 2 3.14 
をしたい場合は、IOArrayとIOモナド内の可変配列を持つことができます
関連する問題