我正在研究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语句控制着数据流,因此我不确定是否有一种干净的方法。
答案 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格式的渲染。
因此:
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