我知道一個可以做布爾運算符:在多個元素
any (>3) [1,2,3,4,5]
,但什麼是實施的優雅的方式:
any and[(>3),(<5)] [1,2,3,4,5]
或
all or[(<2),(>4)] [1,2,3,4,5]
等?
我知道一個可以做布爾運算符:在多個元素
any (>3) [1,2,3,4,5]
,但什麼是實施的優雅的方式:
any and[(>3),(<5)] [1,2,3,4,5]
或
all or[(<2),(>4)] [1,2,3,4,5]
等?
我相信你想檢查是否有任何元素都是(<5)
和(>3)
。
你可以做到這一點是這樣的:
any (\x -> x > 3 && x < 5) [1..5]
和你的另一種能夠通過
any (\x -> x < 2 || x > 4) [1..5]
做,但也許這將是更有趣的定義&&
和||
對職能的工作:
infixr 3 &&&
infixr 3 |||
(&&&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(f &&& g) x = f x && g x
(|||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(f ||| g) x = f x || g x
所以現在我們可以將你的例子改寫爲:
any ((>3) &&& (<5)) [1..5]
any ((<2) ||| (>4)) [1..5]
如果你正在尋找隱藏在任何地方的monad,你還可以將'(&&&)'定義爲'liftM2(&&)' ;) –
那麼''( - >)a''是一個monad,但它通常是一個應用函數,所以在這裏'liftA2'可能更合適(或者直接使用'(&&)<$>(> 3)<*>(<5)')。 – dflemstr
@dflemstr * + 1 *用於應用 –
您還可以定義一個運算符,該運算符通過採用一些Monoid
實例來獲取謂詞列表,如下所示。
test = any (andP [(>3),(<5)]) [1,2,3,4,5]
andP :: [a -> Bool] -> a -> Bool
andP ps = getAll . mconcat (map (All.) ps)
您的符號and[(>3),(<5)]
幾乎可以直接實現爲高階函數。我將其稱爲andP
,因爲any
需要一個謂詞和一個值列表,我們需要一個接受謂詞列表的函數。
andP :: [a -> Bool] -> a -> Bool
andP ps x = all ($ x) ps
現在
andP [(>3), (<5)] x = x > 3 && x < 5
,你可以在你的初始請求寫成
any (andP [(>3), (<5)]) [1,2,3,4,5]
作爲一個側面說明,對於這個特殊的例子,我想更明確的方式是:
between :: (Ord a) => a -> a -> a -> Bool
between lo hi x = lo < x && x < hi
any (between 3 5) [1,2,3,4,5]
另一種方法是使用Monoid
s。當包裝在All
或Any
中時,Bool
是Monoid
,其來自Data.Monoid
。我們需要這樣做,因爲有兩種方式可以合併[Bool]
- 我們可以使用&&
或||
。這就是爲什麼有類型All :: Bool -> All
和Any :: Bool -> Any
這是Monoid
的實例。例如:
> import Data.Monoid
> getAll $ mconcat [All True, All True, All False]
False
> getAll $ mconcat [All True, All True, All True]
True
> getAny $ mconcat [Any True, Any True, Any False]
True
另一個事實是,我們用的是(從Data.Monoid
再次)的Monoid
實例功能:
instance Monoid b => Monoid (a -> b) where
mempty _ = mempty
mappend f g x = f x `mappend` g x
現在我們可以附加功能:
> :t All
All :: Bool -> All
> :t (<5)
(<5) :: (Num a, Ord a) => a -> Bool
> :t All . (<5)
All . (<5) :: (Num a, Ord a) => a -> All
> :t ((All . (<5)) <> (All . (>3)))
((All . (<5)) <> (All . (>3))) :: (Num a, Ord a) => a -> All
> getAll $ ((All . (<5)) <> (All . (>3))) 4
True
歸納這到功能列表:
> getAll $ mconcat [(All. (<5)), (All . (>3))] $ 4
True
> getAll $ mconcat (map (All .) [(<5), (>3)]) $ 4
True
然後搜索http://www.haskell.org/hoogle/爲(a->b) -> [a] -> b
我們看到foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
,我們可以用它代替mconcat . map
:
> import Data.Foldable
> getAll $ foldMap (All .) [(<5), (>3)] $ 4
True
最後映射過來號碼清單:
> map (getAll . foldMap (All .) [(<5), (>3)]) $ [1..5]
[False,False,False,True,False]
> Prelude.or $ map (getAll . foldMap (All .) [(<5), (>3)]) $ [1..5]
True
+1用於具有給定簽名的hoogle搜索 – scravy
您的例子並不正確類型。你是什麼意思'任何和...' –