至少两个Maybes

cla*_*lay 6 haskell maybe

我希望得到最少两个可能的值,或者如果一个没有得到非任何一个,或者如果两个输入都没有则返回任何值.我可以编写一个简单的函数来执行此操作,但我怀疑有一种方法可以在不编写自定义函数的情况下执行此操作.对不起,如果这是一个小问题,但有比使用这个自定义功能更简单的方法吗?

minMaybe :: Ord a => Maybe a -> Maybe a -> Maybe a
minMaybe Nothing b = b
minMaybe a Nothing = a
minMaybe (Just a) (Just b) = Just $ min a b
Run Code Online (Sandbox Code Playgroud)

pig*_*ker 17

使用运算符可以满足规范Control.Applicative.

myMin :: Ord x => Maybe x -> Maybe x -> Maybe x
myMin a b = min <$> a <*> b <|> a <|> b
Run Code Online (Sandbox Code Playgroud)

其中,<|>用于Maybe实施"偏好"

Nothing <|> b  = b
a       <|> _  = a
Run Code Online (Sandbox Code Playgroud)

事情是

min <$> Just a <*> Just b = Just (min a b)
Run Code Online (Sandbox Code Playgroud)

min <$> Just a <*> Nothing = Nothing
Run Code Online (Sandbox Code Playgroud)

这导致了一些错误的答案.使用<|>允许您在min可用时更喜欢计算值,但只有一个时可以使用任何一个恢复Just.

你应该问这样使用是否合适Maybe.由于其Monoid实例的不光彩的例外,它Maybe被设置为模拟容易出错的计算.你在这里有一个Ord带有"顶部"元素的现有扩展.

data Topped x = Val x | Top deriving (Show, Eq, Ord)
Run Code Online (Sandbox Code Playgroud)

你会发现,minTopped x的是你需要的东西.将类型视为数据的表示,而不是结构数据的设备,这是很好的.Nothing通常代表某种失败,因此为您的目的使用不同类型可能更好.

  • `Topped x`有一个合理的`max`,但是如果你想添加一个*bottom*元素,那么预期的语义就会改变,那么为什么类型保持不变呢?当然,我们可以做一次"从半群构造一个monoid"构造,然后将`max`,`min`等包装成半群结构. (3认同)
  • @chi Huh,这意味着如果问题使用了'max`而不是`min`,那么`max`就是一个正确的答案.换句话说,"Bottomed"只是"可能"本身. (2认同)

Zet*_*eta 3

您不能为此使用Applicative, 或实例,因为这些上下文中的任何一个都会使您的总结果为. 话虽这么说,“更简单”这个词是非常固执己见的,而且你的函数本身就很好。MonadNothingNothing

  • 注意:社区 wiki 因为“更简单”是非常固执己见的。 (2认同)