我想知道是否存在與單子通用的列表中的null
等效物或某物。此刻,我試圖找到與== mzero
錯誤的值。但是這種檢查會引起誤報,因爲mzero /= Left "foo"
適用。Haskell檢查monad中的值是否存在
有沒有一種優雅的方式來表達我想要的標準庫?
我想知道是否存在與單子通用的列表中的null
等效物或某物。此刻,我試圖找到與== mzero
錯誤的值。但是這種檢查會引起誤報,因爲mzero /= Left "foo"
適用。Haskell檢查monad中的值是否存在
有沒有一種優雅的方式來表達我想要的標準庫?
概念「包含值」不被Monad
類型類抓獲。畢竟,一個Monad
只給你一些東西順序(>>=
)行動(綁定以前的結果)。 MonadPlus
爲您提供了一種通過mzero
(查看法律和mplus
)「快捷」計算的方法。
但是,能夠包含一個或多個值通常與能夠將所有這些值合併爲一些值攜手。事實上,Data.Foldable
包含一個函數方便也稱爲null
:
> import qualified Data.Foldable as F
>
> showAndTell :: (Show (t a), Foldable t) => t a -> IO()
> showAndTell k =
> putStrLn $ " F.null (" ++ show k ++ ") is " ++ show (F.null k)
> main = do
> putStrLn "Using F.null on 'empty' things:"
> showAndTell $ (Left "Error" :: Either String Int)
> showAndTell $ (Nothing :: Maybe Integer)
> showAndTell $ ([] :: [Double])
>
> putStrLn ""
> putStrLn "Using F.null on 'filled' things:"
> showAndTell $ (Right 123 :: Either String Integer)
> showAndTell $ (Just 123 :: Maybe Integer)
> showAndTell $ ([1,2,3] :: [Int])
結果:
Using F.null on 'empty' things:
F.null (Left "Error") is True
F.null (Nothing) is True
F.null ([]) is True
Using F.null on 'filled' things:
F.null (Right 123) is False
F.null (Just 123) is False
F.null ([1,2,3]) is False
所以,你要尋找的是Foldable
一部分,而不是Monad
。這隻適用於GHC 7.10或更高版本,因爲Data.Foldable.null
是基於4.8.0.0版引入的。如果您堅持使用舊版GHC,您可以使用
> isEmpty :: F.Foldable t => t a -> Bool
> isEmpty = F.foldr (\_ _ -> False) True
我不能當場記住任何簡單的功能,對於所有的單子Maybe
,Either e
,MaybeT m
和ExceptT e m
,這是我能想到的是有「錯誤值」的主要工作單子。
由於GHC 7.10,null
實際上已被推廣(至Foldable
),所以它在前兩個工作。
對於最後三個(Either e
適用於這兩種方法)及其轉換版本,您可以使用catchError
函數。
(雖然最後兩個有Foldable
情況下,他們的null
做錯誤的事情。)
絕對不是來自monad外部的。如果你正在尋找像nonEmpty :: MonadPlus m => m a -> Bool
那麼這是不可能的。
您需要實際運行單子計算來確定它是否爲「空」。但monad可能需要某種輸入來運行(例如State
或甚至Reader
),並且在極端情況下爲IO
,您無法從外部運行monad。現在這些例子不是MonadPlus
在他們自己的AFAICR,但增加他們的失敗(例如MaybeT
),突然有一個明確的定義是什麼意思,他們是「空的」,但仍然適用相同的限制。由於未知的monad可能是其中之一,因此無法獲取任何信息。
可能的簽名可能是nonEmpty :: MonadPlus m => m a -> m Bool
(儘管我不確定它是否具有合理的實現)。但我不認爲這就是你以後的事情,因爲它實際上並不推廣null
;你最終會退出[False]
或[True]
列表(或可能甚至[True, True, True, ...]
與輸入元素數相同),這有點奇怪。
我認爲單子在錯誤的「泛化軸」上是null
;你需要一個比Monad
更好地表徵容器的抽象(許多單子是容器,但很多其他東西都非常不同,所以在任意monads上工作的代碼不能假定容器類屬性)。在GHC-7.10中發生的Foladable
似乎是一個相當不錯的選擇。你或許可以製作一個CanBeEmpty
類型的類,它允許比Foldable
承認更多的東西;我不知道這樣的事情已經存在了。
'可摺疊'完全夠用了。我不知道null是否已經被GHC 7.10推廣了,如果有足夠的類型類,我不想實現類似'Foldable'的東西。 – bash0r
要做的地道的事情不是試圖直接檢測零點,而是提供你想要的行爲,以防零。
這是什麼mplus
或等效(在最近的前奏)<|>
做;它會在第一個操作失敗的情況下鏈接一個操作來運行。這與catchError
支持的Monads上的catchError
相同。它類似於shell或perl編程中常見的成語foo || bar
,意思是運行foo,然後在foo失敗時運行欄。
請注意,在列表monad中它將運行所有選項,但因爲這是列表monad設計工作的原因,所以建模'多種可能性'。
我經常使用<|>
對MaybeT
或EitherT
建模左偏向選擇,即「依次嘗試所有這些選擇,直到一個成功」。
請注意,使用<|>
代替EitherT
確實會丟棄錯誤消息(因爲它將失敗的計算轉換爲後續計算);如果你想保存錯誤信息並以某種方式處理它,那就是你想要的catchError
。
看起來好像你的問題在 – Zeta
@Zeta被打斷了是的,我無意中擊中了鍵盤上的返回鍵。 ^^ – bash0r
我認爲所有單子都會出現一些被視爲「錯誤的價值」(我認爲你的意思是某種錯誤/空白情況)的問題 - 你能否提出一些與以前不同的定義/定律那些MonadPlus? – Carsten