リストのブール値の選択

list y の対応する要素が厳密に正のリスト x の要素が必要であるとします。以下の3つのソリューションのいずれかが動作します。

let x = [1..4]
let y = [1, -1, 2, -2]

[ snd both | both <- zip (map (> 0) y) x, fst both ]

または

map snd $ filter fst $ zip (map (>0) y) x

または

sel :: [Bool] -> [a] -> [a]
sel [] _ = []
sel (True : xs) (y : ys) = y : sel xs ys
sel (False : xs) (y : ys) = sel xs ys

sel (map (> 0) y) x

しかし、これを促したのは、R言語では、これは次のようにコンパクトに書くことができるということでした。

x[y > 0]

and given how much shまたはter that is I was wondering if there is a shまたはter/better way to do this in Haskell?

2

4 答え

私はhaskellの専門家ではありませんが、なぜリストの理解力を使用しないのですか?

 [i | (i,j)  <-  zip x y, j > 0 ]
10
追加された
非常に良い答え。
追加された 著者 user1189687,
zip x y >>= \(a,b) -> filter(const(b>0)) [a]

または、無意識のうちにApplicativeを使用して...

import Control.Applicative

zip x y >>= filter <$> const.(>0).snd <*> (:[]).fst
1
追加された

言語拡張を使用する場合は、

{-# LANGUAGE ParallelListComp #-}

bfilter :: (b -> Bool) -> [a] -> [b] -> [a]
bfilter cond xs ys = [x | x <- xs | y <- ys, cond y]

Haskellには、R版とほぼ同じくらい短いものはありません。Rでは、組み込みの言語だからですが、Haskellではそうではありません。どうやらRを設計した人は、そのようなプリミティブを含む良い理由があると思ったのですが、Haskellのデザイナーの誰もその言語にそのような構造を含める理由を説得することはできませんでした(そして、うまくはまりません。その決定 - それはRにうまく収まるかもしれない、私はその言語を知らない)。

1
追加された
それは同じことですか?私が理解しているように、2つの関係はありません。つまり、どちらもリスト型(Rで配列)の型エンティティを持ち、対応するインデックスの要素の条件に基づいてエントリを選択します(ちなみに、 x y の長さが異なる場合、Rは動作しますか?Haskellと同じですが、実行時間の短いエラーの終わりで停止しますか? y mytable の一部でない場合でも、 y が可能なら select x from mytable y> 0 ですか?
追加された 著者 Daniel Fischer,
私は理解していない。選択を行うのはHaskellとRのように簡単ですが、Rには特別な構文がありますが、Haskellでは独自の関数を定義する必要があります。 Rのデザイナーが操作のための特別な構文を追加するのに十分重要だと思っていると仮定することができるので、Rのそれ自身の関数を書くのはハスケルよりもはるかに難しいと思います。 x y の長さが異なる場合、Rの x [y> 0] のセマンティクスについてはまだ興味があります。
追加された 著者 Daniel Fischer,
Rだけでなく、選択が基本的なものとみなされるリレーショナルデータベースでも、組み込みに関するステートメントについて言及してください。たとえば、SQLでは select x from mytable y> 0 となります。
追加された 著者 user1189687,
私は、比較可能性(同じ長さ、同じテーブルなど)のために必要なものを想定することができると思います。問題の要点は、選択の実行が容易であることです。
追加された 著者 user1189687,
Rでは、 x < - 1:3; y < - c(1、-1,2、-2); 1 3 x [y <0] 2 NA となります。 y <0 y> 0 のリサイクルは同じ y ではなく x < - 1:5 x [y <0] 1 4 5 2 4
追加された 著者 user1189687,

ダニエルフィッシャーが言っているように、このための特別な構文はありません。

この操作を頻繁に行う場合は、毎回手動でリスト内包またはマップ/フィルターチェーンを組み立てるのではなく、独自の単一の再利用可能な関数を定義することをお勧めします。 (呼び出し側が map を別途適用する必要があるため、このテストに sel は合格しません)。

そう

selectWhere :: [a] -> (a -> Bool) -> [b] -> [b]
selectWhere ys pred = map snd . filter (pred . fst) . zip ys
-- call it like this:  selectWhere y (> 0) x

またはあなたが好むより明確な定義。重要なことは、あなたが関数内でそれを包むことです。

1
追加された