18

Reddit のユーザーが次のコードを教えてくれました。

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

ここで何が起こっているかというと、リバースやテールまたはヘッドの取得など、処理できる一連の操作があります。

素晴らしい。

私がやりたいことは、個々の要素に入り込み、それらを永久に変更することです. たとえば、次のようなことができるようになりたいです。

ns !! 0

[print, 1] のようなものを取得し、最後の要素をたとえば 3.14 に変更して、関数が 3.14 を出力するようにします。

Haskellでそれはまったく可能ですか、それともLISPに戻るべきですか?

重要な編集:私はちょっと大失敗しました。新しいリストを作成する必要があることを理解しています。リストの一部である関数の引数を取得することは可能ですか? 私が欲しいのは、関数をその識別子/引数から構成し、評価される前に関数を識別子/引数に分解できることです。

4

4 に答える 4

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
于 2009-08-18T20:13:20.240 に答える
4

リストを変更しますか? あなたはLispに戻るべきです;-)

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

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

編集:編集された質問を完全には理解できませんが、関数と引数をデータとして別々に処理し、後で「適用」することができます。

do
    let ns = [(print, 1), (print, 2), (print, 3)]
    sequence_ $ map (\(f,a)->f a) ns
于 2009-08-18T18:57:20.673 に答える
1

同様に、Haskell の方法は新しいリストを作成することですが、本当に必要な場合は、IOArray を使用して IO モナド内に変更可能な配列を含めることができます。

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
于 2009-08-19T01:52:58.350 に答える