gpt4 book ai didi

haskell - 在这个例子中,我对绑定(bind)运算符的 Haskell 定义有什么问题?

转载 作者:行者123 更新时间:2023-12-04 22:30:29 25 4
gpt4 key购买 nike

我正在关注 monad 转换器教程 here .

At this point in the tutorial ,它要求我尝试为 EitherIO 实现 Monad 实例数据类型,定义为:

data EitherIO e a = EitherIO {
runEitherIO :: IO (Either e a)
}

所以我尝试了:
instance Functor (EitherIO e) where
fmap f = EitherIO . fmap (fmap f) . runEitherIO

instance Monad (EitherIO e) where
return = EitherIO . return . Right
x >>= f = join $ fmap f x

教程的版本有点不同:
instance Monad (EitherIO e) where
return = pure -- the same as EitherIO . return . Right
x >>= f = EitherIO $ runEitherIO x >>= either (return . Left) (runEitherIO . f)

现在,所有类型都适合,所以我认为我很好,并祝贺自己终于找到了 join 的用途。 .

事实证明, further down the tutorial , 我被要求运行 runEitherIO getToken关于以下内容:
liftEither x = EitherIO (return x)
liftIO x = EitherIO (fmap Right x)

getToken = do
liftIO (T.putStrLn "Enter email address:")
input <- liftIO T.getLine
liftEither (getDomain input)

使用我的 >>= 版本运算符(operator),GHCi 在我提供一些输入后会挂起。然后即使在我通过 ^C 打断之后,GHCi 会开始表现得很奇怪,在我打字的时候会挂一两秒钟。我必须杀死 GHCi 才能重新启动。当我更换 >>=定义与教程定义,一切正常。

我的完整文件是 here .

所以:
  • 我的定义有什么问题?
  • 为什么 GHCi 会进行类型检查,然后表现得像以前那样?这是 GHCi 错误吗?
  • 最佳答案

    我的猜测是,这是罪魁祸首:

    instance Monad (EitherIO e) where
    return = EitherIO . return . Right
    x >>= f = join $ fmap f x

    但是, join定义为:
    join x = x >>= id

    但是,这样 join>>=以相互递归的方式定义,导致非终止。

    请注意,这种类型的检查与以下内容非常相似:
    f, g :: Int -> Int
    f x = g x
    g x = f x

    底线:您应该为 >>= 提供定义不涉及 join .

    关于haskell - 在这个例子中,我对绑定(bind)运算符的 Haskell 定义有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28662311/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com