1

関数の定義に関して、haskell の演習を行っています。これは、一連の相互作用を実行し、その結果をリストに蓄積する :: [IO a] -> IO [a] です。

私を混乱させるのは、IO a のリストを表現する方法ですか? (アクション:アクション)??

IO を使用して再帰コードを記述する方法??

これは私のコードですが、これらにはいくつかの問題があります...

accumulate :: [IO a] -> IO [a]
accumulate (action:actions) = do 
                                value <- action
                                list <- accumulate (action:actions)
                                return (convert_to_list value list)


convert_to_list:: Num a =>a -> [a]-> [a]
convert_to_list a [] = a:[]
convert_to_list x xs = x:xs
4

4 に答える 4

5

あなたが実装しようとしているのはsequenceからControl.Monadです。

答えるのではなく、答えを見つけられるようにするには、hoogle[IO a] -> IO [a]で検索してみてください(関数を選択すると、ページの右側に [ソース] リンクがあります)。

アクションのリストが空のリストの場合に何が起こるかをコードで確認し、シーケンスがそれを処理するために何をするかを確認してください。

于 2012-09-30T07:20:46.667 に答える
2

すでにそのような関数がControl.Monadあり、それが呼び出されましたsequence(いいえ、それを見ないでください)。命名時に下された重要な決定を示す必要があります。技術的には、これらの s を互いに接続する[IO a]順序については何も述べていませんが、名前には順次接続するという意味があります。Monadsequence

あなたの問題を解決するために。タイプをもっと見て、@sacundimのアドバイスを受けることをお勧めします。GHCi (Glasgow Haskell Compiler のインタープリター) には、型をチェックして式を理解するための非常に優れた方法があります (:t (:)(:) :: a -> [a] -> [a]、独自の関数の 1 つを思い起こさせますが、型の制限が少ないことを思い出させるはずです)。

まず第一に、あなたが示したものをもっと簡単な例で見てみたいと思います。

data MyWrap a = MyWrap a

accumulate :: [MyWrap a] -> MyWrap [a]
accumulate (action:actions) = MyWrap (convert_to_list value values) where
    MyWrap value = action -- use the pattern matching to unwrap value from action
    -- other variant is:
    -- value = case action of
    --             MyWrap x -> x
    MyWrap values = accumulate (action:actions)

私はあなたが意図的に犯したのと同じ過ちを犯しましたが、わずかな違いがあります (valuesはヒントです)。おそらくすでに言われているように、適切な関数定義をインライン化することで、プログラムを解釈することができます。つまり、等号 ( =) の左側の定義を一致させ、右側に置き換えます。あなたの場合、無限のサイクルがあります。このサンプルまたはあなたのサンプルで解決してみてください。理解できると思います (ところで、あなたの問題は単なるタイプミスである可能性があります)。

更新:プログラムが実行時にパターン マッチに関するメッセージが表示されても怖がらないでください。関数を次のように呼び出すときのケースを考えてくださいaccumulate []

于 2012-09-30T07:20:37.213 に答える
1

sequenceおそらく、マップする関数を探しています[m a] -> m [a]か?

于 2012-09-30T07:17:56.057 に答える
1

したがって、あなたの質問に対する答えの短いバージョンは、コードに (ほとんど) 何も問題がないということです。

まず、型チェックを行います:

Prelude> let accumulate (action:actions) = do { value <- action ; 
          list <- accumulate (action:actions) ; return (value:list) }
Prelude> :t accumulate
accumulate :: (Monad m) => [m t] -> m [t]

なぜ私はreturn (value:list)そこを使ったのですか?2 番目の関数を見てください(:)。通話中g

g a [] = a:[]
g a xs = a:xs

(:)同じ引数で呼び出すのと同じです。これは、「イータ削減」として知られているものです( 「同等である」と(\x-> g x) === g読みます)。===

したがって、コードに残る問題は 1 つだけです。すでにアクションから値value <- actionを取り出しているのに、なぜそのアクションを で再利用するのlist <- accumulate (action:actions)でしょうか? 本当にしなければならないのですか?今、あなたは、例えば、

accumulate [a,b,c]  ===
do { v1<-a; ls<-accumulate [a,b,c]; return (v1:ls) } ===
do { v1<-a; v2<-a; ls<-accumulate [a,b,c]; return (v1:v2:ls) } ===
do { v1<-a; v2<-a; v3<-a; ls<-accumulate [a,b,c]; return (v1:v2:v3:ls) } ===
.....

1 つの簡単な修正で完了です。

于 2012-10-01T02:42:52.637 に答える