5

foldlを使用して次の関数を実行する方法を見つけようとしています。

count a = length (filter (\i -> i) a)

ブール値のリストで真である値の数をカウントするだけです。自分で試してみました

count = foldl (\i -> 
            case i of
                True -> (1+)
                False -> (0+)
            ) 0

コンパイルすらしなかった。助言がありますか?

4

2 に答える 2

9

それでは、関連する関数の種類を確認しましょう

Prelude> :t (\i -> case i of { True -> (1+) ; False -> (0+) })
(\i -> case i of { True -> (1+) ; False -> (0+) }) :: (Num t) => Bool -> t -> t
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a

したがって、sのリストではBool、bはBoolですが、使用している関数はBool、2番目ではなく、最初の引数として持っています。累積値が最初の引数です。代わりにあなたはすることができます

foldl (\acc p -> case p of { True -> acc + 1 ; False -> acc }) 0

または、引数の順序を修正したい場合は、元の関数を次のように使用します。flip

Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c

foldl (flip (\i -> case i of
                           True -> (1+)
                           False -> (0+)
             )) 0

または、より簡潔にすることもできます。foldl (flip ((+) . fromEnum)) 0

于 2009-02-21T21:20:22.653 に答える
4

どうですか:

count = foldl (\i v -> if v then i + 1 else i) 0

なしでそれを行う別の方法foldl

count list = sum $ map fromEnum list

指摘してくれたLoganの功績fromEnum。これまで聞いたことがありませんでした。

于 2009-02-21T21:20:23.933 に答える