當我們搜索“最大值”并且不方便找到最小值時,也許很有用
-- update maximum could be used as "lambda"
updateMaximum :: (Ord a) => Maybe a -> Maybe a -> Maybe a
updateMaximum saved new = max new saved
-- update minimum could't be used as "lambda"
updateMinimum Nothing new = new
updateMinimum saved Nothing = saved
updateMininum saved new = min new saved
理想的解決方案是帶有另一個建構式順序的標準monad,但我沒有找到它:
data Maybe' a = Just' a | Notheing'
-- all standard functions implementations:
safeHaad' :: [a] -> Maybe' a
...
所以問題是:在haskell中撰寫“updateMinimum”函式的標準方法是什么?
PS 有兩種可能的解決方案,但每種都有其自身的缺點:
- 更改問題措辭:找到函式“f()”的最小值 -> 找到函式“0-f()”的最大值
- 將“MyMaybe”與交換的建構式順序一起使用:data MyMaybe a = Value a | 沒有
uj5u.com熱心網友回復:
您真的不希望 Nothing 成為此處排序的一部分,而是在執行二元運算時“被忽略”,或者換句話說,就像一個身份一樣。這是 Maybe 的 Monoid 行為,我們可以使用 Semigroup 實體 Min 和 Max。
updateMinimum x y = fmap getMin (fmap Min x <> fmap Min y)
updateMaximum x y = fmap getMax (fmap Max x <> fmap Max y)
無點版本并不是真正的改進,但它看起來像這樣:
updateMinimum = (fmap getMin .) . ((<>) `on` fmap Min)
uj5u.com熱心網友回復:
monoid-extras 包提供了Inf資料型別、變體PosInf和NegInf,正是為了這個目的。您的兩個函式如下所示:
updateMaximum :: Ord a => NegInf a -> NegInf a -> NegInf a
updateMaximum = max
updateMinimum :: Ord a => PosInf a -> PosInf a -> PosInf a
updateMinimum = min
我什至懶得命名它們。
uj5u.com熱心網友回復:
您可以暫時包裝 with Down,顛倒順序,max在顛倒的順序下取 ,然后稍后解包:
import Data.Ord
updateMaximum :: Ord a => Maybe a -> Maybe a -> Maybe a
updateMaximum x y = max x y
updateMinimum :: Ord a => Maybe a -> Maybe a -> Maybe a
updateMinimum x y = getDown <$> max (Down <$> x) (Down <$> y)
注意微妙的部分:我們包裹在Maybe, 所以Nothing即使我們顛倒了順序,它仍然是最小值。這使得max做正確的事。
一些測驗證實這可以根據需要進行。下面,前兩個值是測驗輸入,第三個是輸出。
max: (Nothing,Nothing,Nothing)
min: (Nothing,Nothing,Nothing)
max: (Nothing,Just 1,Just 1)
min: (Nothing,Just 1,Just 1)
max: (Nothing,Just 2,Just 2)
min: (Nothing,Just 2,Just 2)
max: (Just 1,Nothing,Just 1)
min: (Just 1,Nothing,Just 1)
max: (Just 1,Just 1,Just 1)
min: (Just 1,Just 1,Just 1)
max: (Just 1,Just 2,Just 2)
min: (Just 1,Just 2,Just 1)
max: (Just 2,Nothing,Just 2)
min: (Just 2,Nothing,Just 2)
max: (Just 2,Just 1,Just 2)
min: (Just 2,Just 1,Just 1)
max: (Just 2,Just 2,Just 2)
min: (Just 2,Just 2,Just 2)
完整代碼:
module Main where
import Data.Foldable
import Data.Ord
updateMaximum :: Ord a => Maybe a -> Maybe a -> Maybe a
updateMaximum x y = max x y
updateMinimum :: Ord a => Maybe a -> Maybe a -> Maybe a
updateMinimum x y = getDown <$> max (Down <$> x) (Down <$> y)
main :: IO ()
main = do
let xs = [ Nothing, Just 1, Just 2 ] :: [Maybe Int]
for_ xs $ \x ->
for_ xs $ \y -> do
putStr "max: "
print (x, y, updateMaximum x y)
putStr "min: "
print (x, y, updateMinimum x y)
pure ()
uj5u.com熱心網友回復:
基于大衛弗萊徹的回答,甚至還有一個更簡潔的解決方案,它仍然是免費的,但我感覺更清楚一些,因為它將復雜的雙重使用隱藏在模塊.中的臨時運算子中:.:Data.Composition
import Data.Function (on)
import Data.Semigroup
import Data.Composition ((.:))
-- (.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
updateMinimum :: (Ord a) => Maybe a -> Maybe a -> Maybe a
updateMinimum = fmap getMin .: ((<>) `on` fmap Min)
其中 的定義updateMinimum對此資料流進行編碼
┌───────────┐
┌┤fmap getMin├─ first input
┌───────────┐ ┌────┐ │└───────────┘
output ─┤fmap getMin├──┤(<>)├─┤
└───────────┘ └────┘ │┌───────────┐
└┤fmap getMin├─ second input
└───────────┘
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/427308.html
下一篇:haskell在哪里保存狀態?
