仅当函数可能导致错误以保持类型安全时才使用Maybe monad吗?
在我当前的项目中,我正在对列表进行操作,对于我的get / set函数,我使用Maybe monad来防止越界错误:
getCell :: [String] -> Int -> Int -> Maybe [String]
setCell :: [String] -> Int -> Int -> Maybe [String]
对我来说,这就像使用此Monad的正确方法。
在不涉及项目细节的情况下,我还有另一个函数来处理列表,如果有解决方案,则返回列表。
问题是,由于没有什么可导致计算错误的内容,此函数应始终返回[String]
还是我应该使用Maybe [String]
表示计算未找到解决方案?
solve :: [String] -> [String]
-- Found -> [String], Not found -> []
solve :: [String] -> Maybe [String]
-- Found -> Just [String], Not found -> Nothing
答案 0 :(得分:1)
我喜欢Haskell的原因之一是类型系统表现力强。如果对函数进行了精心设计,则函数的类型将代替很多(尽管不是全部!)文档。
Maybe
通常用于指示函数调用可能失败。一个典型的例子是lookup
:
Prelude> :t lookup
lookup :: Eq a => a -> [(a, b)] -> Maybe b
在这里,您正在尝试在关联列表中查找值,并且很明显,如果键不在列表中,则该操作可能会失败。在这种情况下,只有一件事会出错,因此除了是否存在返回值外,您不需要任何其他信息。
但是,有时操作可能会以多种方式失败,并且您希望给呼叫者一个机会来区分各种不同的原因。在这种情况下,Either
是一个更好的选择,因为您可以让 left 案例包含有关错误类型的信息。
最后,返回列表时,有时可以使用空白列表来表示找不到其他结果。
然后,将列表包装在Maybe
中仅在空列表[]
与Nothing
根本不同的情况下有用。如果我看到一个返回Maybe []
的函数,我知道作为调用者,我将不得不处理Nothing
,而且还要处理任何列表值,包括空列表。
仅通过查看OP中的类型签名,我不清楚Nothing
与[]
有何不同,但这可能只是我缺乏对特定域的深入了解被建模。 确实,但是似乎有点奇怪。