也许Monad的用法

时间:2018-12-01 14:37:43

标签: haskell

仅当函数可能导致错误以保持类型安全时才使用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

1 个答案:

答案 0 :(得分:1)

我喜欢Haskell的原因之一是类型系统表现力强。如果对函数进行了精心设计,则函数的类型将代替很多(尽管不是全部!)文档。

Maybe通常用于指示函数调用可能失败。一个典型的例子是lookup

Prelude> :t lookup
lookup :: Eq a => a -> [(a, b)] -> Maybe b

在这里,您正在尝试在关联列表中查找值,并且很明显,如果键不在列表中,则该操作可能会失败。在这种情况下,只有一件事会出错,因此除了是否存在返回值外,您不需要任何其他信息。

但是,有时操作可能会以多种方式失败,并且您希望给呼叫者一个机会来区分各种不同的原因。在这种情况下,Either是一个更好的选择,因为您可以让 left 案例包含有关错误类型的信息。

最后,返回列表时,有时可以使用空白列表来表示找不到其他结果。

然后,将列表包装在Maybe中仅在空列表[]Nothing根本不同的情况下有用。如果我看到一个返回Maybe []的函数,我知道作为调用者,我将不得不处理Nothing,而且还要处理任何列表值,包括空列表。

仅通过查看OP中的类型签名,我不清楚Nothing[]有何不同,但这可能只是我缺乏对特定域的深入了解被建模。 确实,但是似乎有点奇怪。