2017-06-01 7 views
2

ハスケルを新しくして[[(Int, Int)]]を構築しようとしました。ここで、各要素は対応するグリッド位置です。別のボード[[a]]から構成されています。したがって、辺の長さ3の正方形の[[a]]は、インデックス、要素タプルに要素をスローする

[[(0, 0), (1, 0), (2, 0)] 
,[(0, 1), (1, 1), (2, 1)] 
,[(0, 2), (1, 2), (2, 2)]] 

私は大規模な簡単に何かが欠けていますので、もし(最終的に私は、[[b]]を作成するタイプ[[a]] -> (Int, Int) -> bの関数にmap (map ...)でこれを反復処理することがありますを作成します私に知らせて)

にPythonでは、私のようなものするかもしれない!と言うことです

[[(x,y) for (x,_) in enumerate(board[y])] for (y,_) in enumerate(board)] 

を、私はを構築するためにenumerate組み込みを使用したいです0つのタプルと要素を捨てる。

私は私が行うことができますHaskellで知っている:

[[(x,y) | x <- [0..length (board!!y)-1]] | y <- [0..length board-1]] 

が、パイソン(for foo in range(len(bar)))における構造のものと種類がアンチパターンと大きく落胆のビットです。ハスケルでもそうですか?私は、私は、Pythonを書きたいようハスケルを書くとしたら

することは、私がやるだろう:

[[(x,y) | (x,_) <- zip [0..] (board!!y)] | (y,_) <- zip [0..] board] 

をひんしゅくを買うことですか?

+0

もっと一般的には、よく書かれていて慣用的であれば、Pythonでは「Pythonic」と言います。 "Haskellion"構造のための類似の用語がここにありますか? –

答えて

4

あなたの最終的な「Pythonのような書き込み」の提案はほとんど役に立ちますが、ボードの行を不必要に投げ捨てて、(!!)で再作成しています。このようにそれを書くことは代わりに完全に罰金のようになります。

board :: [[Char]] 
board = ["abc", "def", "ghi"] 

board' :: [[(Int, Int)]] 
board' = [[(x, y) | (x, _) <- zip [0..] row] 
        | (y, row) <- zip [0..] board] 
+0

これは完璧です。なぜ私は自分自身を考えなかったのか分かりません - ありがとう! –

2

まあ普通(!!) :: [a] -> Int -> aは本当に素敵なオペレータではありません:それはO(k)はK番目の要素にアクセスするための時間を要します。あなたの小さな例では、実際問題ではありませんが、いくつかのアルゴリズムをO(n)からO(n 2)に変更することができます。

は通常Haskellで、一つは リストを反復、代わりの は(ランダム)インデックスを取得することができ巧妙なアルゴリズムを書くことで、それを回避することを目的とします。Pythonで

あなたを書き換えることができますに

[[(x,y) for (x,_) in enumerate(board[y])] for (y,_) in enumerate(board)] 

[[(x,y) for (x,_) in enumerate(by)] for (y,by) in enumerate(board)]

とハスケルの等価は次のようになります。

[ [ (x,y) | (x,_) <- zip [0..] by ] | (y,by) <- zip [0..] board ] 

それとも私たちがして、コードクリーナーを作ることができます最初にHaskellでenumerate :: (Enum a, Num a) => [b] -> [(a, b)]関数を導入する:

その後、
enumerate :: (Enum a, Num a) => [b] -> [(a, b)] 
enumerate = zip [0..] 

と書き込み:

[ [ (x,y) | (x,_) <- enumerate by ] | (y,by) <- enumerate board ] 
1

あなたはさておき、あなたが以下の機能に興味があるかもしれない示唆しているようだ、時々mapWithIndexと呼ばれる(例えば、in containers)時にはimapin lens)と呼ばれます。

mapWithIndex :: (Int -> a -> b) -> [a] -> [b] 
mapWithIndex f = go 0 
    where 
    go !_i [] = [] 
    go i (x : xs) = f i x : go (i + 1) xs 

したがってmapWithIndex (\i -> mapWithIndex (\j y -> (i,j,y)))は、リストのリストを取り、各要素にその位置を注釈します。もちろん、注釈を付けるのではなく、任意の計算を実行できます。

関連する問題