具有“真实”返回功能的monad

时间:2014-01-11 18:36:33

标签: haskell monads

常见的初学者错误是看return并认为它是一个语言关键字,它以退货值退出当前函数。当然,我们知道它根本不是它的功能。但我想知道......我们真的可以制作这样的功能吗?纯粹是出于争论的缘故,在这一点上。

似乎我们正在寻找一些具有功能的monad Foo

exit :: x -> Foo x

将中止剩余的计算并立即返回x

这样的事情是否可以构建?如果它可以构建,它会有用吗?这甚至是一个理智的事情吗?

4 个答案:

答案 0 :(得分:7)

是的,可以在Cont monad中使用。 Cont定义如下:

newtype Cont r a = Cont {runCont :: (a -> r) -> r}

instance Monad (Cont r) where
    return a = Cont ($ a)
    m >>= k = Cont $ \c -> runCont m $ \a -> runCont (k a) c

现在我们可以按如下方式创建exit

exit = Cont . const

事实上,您可以在几乎任何monad中执行此操作(例如,您可以在Either monad中执行此操作,但不能在State monad中执行此操作。然而,Cont monad是所有monad的母亲:http://blog.sigfpe.com/2008/12/mother-of-all-monads.html

答案 1 :(得分:5)

当然可行。它甚至已经在标准库中了。你只需要一个稍微更健全的签名。

import Control.Monad

exit :: a -> Either a b
exit = Left

main = print $ do
    x <- Right 5
    exit "foo"
    error "this is a good place to crash"

需要注意的重要一点是,救助时给出的类型不是免费的 - 它必须与Either的类型相匹配。

答案 2 :(得分:1)

如果你想满足monad法则,你肯定不能称之为return,因为我们需要return a >>= f = f a

另外,我认为根据给出的精确规格,它根本不存在。假设x :: af :: a -> Foo b,然后只是按照类型exit a >>= f :: Foo b,我们希望它生成x :: a

答案 3 :(得分:1)

看来你可以实现这个:

data Foo e x =
  Next x |
  Done e

instance Monad (Foo e) where
  return = Next

  (Next x) >>= f = f x
  (Done e) >>= f = Done e

exit :: e -> Foo e x
exit = Done

run :: Foo x x -> x
run (Next x) = x
run (Done x) = x

注意monad有一个额外的类型参数;我认为不可能避免这种情况。基本上Foo e x生成x并且“最终”生成e。请注意,run函数需要两种类型匹配;您可以同样要求run仅在exit被某个地方调用时才有效,或者其他一些可能性......

所以,是的,你可以构建这个,不,它不是特别有用的AFAIK。