我正在尋找一個基本類似於列表mapM
的函數 - 它執行一系列以列表中的每個值作爲參數的monadic動作 - 並且每個monadic函數返回m (Maybe b)
。但是,我希望它在第一個參數導致函數返回值Just
後停止,之後不再執行,並返回該值。在Haskell中實現「findM」?
那麼,它可能會更容易只顯示類型簽名:
findM :: (Monad m) => (a -> m (Maybe b)) -> [a] -> m (Maybe b)
其中b是第一Just
值。結果中的Maybe
來自find
ing(在空列表等的情況下),並且與由Monadic函數返回的Maybe
無關。
我似乎無法用一個簡單的庫函數應用程序來實現它。我可以用
findM f xs = fmap (fmap fromJust . find isJust) $ mapM f xs
這將工作,但我試用了一下,似乎所有的單子行動呼籲find
之前執行的,所以我不能靠懶惰這裏。
ghci> findM (\x -> print x >> return (Just x)) [1,2,3]
1
2
3
-- returning IO (Just 1)
實現此功能的最佳方式是在第一次「正確」返回後不會執行monadic操作?東西會做:
ghci> findM (\x -> print x >> return (Just x)) [1,2,3]
1
-- returning IO (Just 1)
甚至,理想情況下,
ghci> findM (\x -> print x >> return (Just x)) [1..]
1
-- returning IO (Just 1)
希望有不使用顯式的遞歸,並且如果可能的庫函數組成一個答案?或者,甚至可能是一個免費之一?
哈!看起來我們在同一時間有完全相同的想法。雖然你有點快。 :) – shang
是的。 'Maybe'的'MonadPlus'實例中的'mzero'和'mplus'與'Maybe'的'Alternative'實例中的'empty'和'<|>'完全相同。 'MaybeT'的'mzero'和'mplus'是'return Nothing'和我定義的'<||>'函數,除了用我的原始答案和jozefg的答案來寫。我們所缺少的關於這個問題的完整論文是解釋如何從查看'(Monad m)=> m。 f'爲f寫一個monad變換器,以便你可以替換m。 f'帶一個新的數據類型,所以你可以開始寫它的實例。 – Cirdec
@Cirdec我更新了答案。在一般情況下,可能無法構建這樣的變壓器,但我們實際上並不需要。有足夠的幺半羣並摺疊它。 –