是否有一种无条件的方法将条件检查转换为输入的Maybe类型?

时间:2015-12-30 18:28:40

标签: haskell pointfree maybe

我正在研究haskell中的一些简单练习,并想知道是否有一种无点的方法将if-then-else语句转换为Maybe类型:Nothing如果返回条件为false,如果条件为真,则为Just输入。

简而言之,给出一些:

maybeIf :: (a -> Bool) -> a -> Maybe a
maybeIf cond a = if cond a then Just a else Nothing

是否存在与a无关的实现?我也在查看更具体的版本,a -> Maybe a,并且感觉Control.Arrow中某处可能有答案。但是,由于Maybe是数据类型而if-else语句控制着数据流,因此我不确定是否有一种干净的方法。

5 个答案:

答案 0 :(得分:7)

妨碍制作该免费点的主要因素是if / then / else。您可以定义if'组合子,也可以使用我定义和使用的通用版本:

ensure p x = x <$ guard (p x)

标准工具提供连续的无点版本

ensure p = ap (<$) (guard . p)
ensure = ap (<$) . (guard .)

虽然我真的不认为要么比有点版本更好。

答案 1 :(得分:7)

您可以从find导入Data.Foldable,然后就可以了:

import Data.Foldable(find)

maybeIf cond = find cond . Just

函数find并不复杂,因此您可以根据Maybe轻松地自己定义它,但实际上它与您自己的{{1}实现没有太大区别所以你可能不会获得太多收益,这取决于你想要这样做的原因。

答案 2 :(得分:3)

如果我们选择教会编码为布尔人......

truth :: Bool -> a -> a -> a
truth True  t f = t
truth False t f = f

然后我们可以用Applicative-style编写一个无点maybeIf

maybeIf :: (a -> Bool) -> a -> Maybe a
maybeIf = liftA3 truth <*> pure Just <*> pure (pure Nothing)

一些直觉......

f <$> m₁ <*> … <*> mₙ = \x -> f (m₁ x) … (mₙ x)
liftAₙ f <$> m₁ <*> … <*> mₙ = \x -> f <$> m₁ x <*> … <*> mₙ x

如果你安装的字体不支持所需的unicode字符,这是以上#34;直觉&#34;的PNG格式的渲染。

enter image description here

因此:

liftA3 truth <*> pure Just <*> pure (pure Nothing)
= liftA3 truth <$> id <*> pure Just <*> pure (pure Nothing)
= \p -> truth <$> id p <*> (pure Just) p <*> (pure (pure Nothing)) p
= \p -> truth <$> p <*> Just <*> pure Nothing
= \p -> \a -> truth (p a) (Just a) ((pure Nothing) a)
= \p -> \a -> truth (p a) (Just a) Nothing

答案 3 :(得分:3)

关注dfeuer's lead(并使用Daniel Wagner的新名称),

join

join :: Monad m => m (m a) -> m a是一个monadic函数join k x = k x x (k =<< f) x = k (f x) x ,但对于函数它只是

join

join被接受为免费代码中W combinator的替代。

你只想让它与value参数无关,但很容易用 = join ((bool (const Nothing) Just .) p) = (join . (bool (const Nothing) Just .)) p 进一步转换方程(结果的可读性完全是另一个问题),如

 #> (join . (bool (const Nothing) Just .)) even 3
Nothing

 #> (bool (const Nothing) Just =<<) even 4
Just 4

实际上,

\p x -> listToMaybe [x | p x]

但我更愿意在实际代码中看到\p x -> [x | p x]

或只是x <$ guard (p x),Monad Comprehensions。哪个 Daniel Wagner's .donate-hero { background: #485563 url(../img/donate-bg.jpg) no-repeat center center; background-size: cover; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; height: 100%; } 相同,只是语法不同。

答案 4 :(得分:1)

此函数在Control.Monad.Plus中定义,并称为partial