gpt4 book ai didi

haskell - 如何编写使用 ReaderT 和 Either 运行的函数?

转载 作者:行者123 更新时间:2023-12-02 14:02:36 26 4
gpt4 key购买 nike

是否可以将以下函数重写为单行函数?

action :: NewTenant -> AppM (Either TenantCreationError Tenant)
action newTenant = (createTenant newTenant) >>= \case
Left x -> return $ Left x
Right y -> do
t <- activateTenant $ (y ^. key)
return $ Right t

type AppM = ReaderT AppConfig IO
createTenant :: NewTenant -> AppM (Either TenantCreationError Tenant)
activateTenant :: TenantId -> AppM Tenant

最佳答案

可能最好的方法是包含 ExceptT或类似的 AppM单子(monad)。然后你将为 createTenant 赋予新类型和activateTenant :

createTenant :: NewTenant -> AppM Tenant
activateTenant :: TenantId -> AppM Tenant

action :: NewTenant -> AppM Tenant
action = activateTenant . view key <=< createTenant

您可以使用 ExceptT 将旧函数转换为新的 monad 堆栈。 (对于 createTenant )和 lift (对于 activateTenant )。

如果由于某种原因这种方法不可行,那么您可以使代码适本地不可读:

action = createTenant >=> either (return . Left) (\y -> Right <$> activateTenant (y ^. key))

推杆的一个缺点ExceptT在你的AppM monad 的缺点是你无法区分可能失败和不能失败的操作。如果这对您很重要,您有几个选择。

  1. 使用ExcepT本地仅用于其实例。你会保留AppM按原样和 createTenant 的类型和activateTenant按原样,但写

    action newTenant = runExceptT $ do
    y <- ExcepT (createTenant newTenant)
    lift (activateTenant (y ^. key))

    或其等效的一行:

    action n = runExcepT (ExceptT (createTenant n) >>= lift . activateTenant . view key)
  2. 使您的操作的效果具有多态性。您仍然会包括 ExceptTAppM monad,但是 createTenant 的类型和activateTenant现在将是

    createTenant :: (MonadReader AppConfig m, MonadIO m, MonadThrow TenantCreationError m)
    => NewTenant -> m Tenant
    activateTenant :: (MonadReader AppConfig m, MonadIO m)
    => TenantId -> m Tenant

    action :: (MonadReader AppConfig m, MonadIO m, MonadThrow TenantCreationError m)
    => NewTenant => m Tenant
    action = activateTenant . view key <=< createTenant

    然后您将特别能够给出 action单态型AppM Tenant ;从 activateTenant 的类型中仍然可以清楚地看出它不会失败。而且,它会让你有机会说出以前不能说的话;例如如果newTenant不需要做IO您可以通过删除 MonadIO m 来表明这一点来自其类型的限制。您可以通过为您希望最常使用的组合定义类型同义词来恢复短类型签名,例如

    type ConfigIO m = (MonadReader AppConfig m, MonadIO m)
    type Failable m = (ConfigIO m, MonadThrow TenantCreationError m)
    createTenant :: Failable m => NewTenant -> m Tenant
    activateTenant :: ConfigIO m => TenantId -> m Tenant

关于haskell - 如何编写使用 ReaderT 和 Either 运行的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39689887/

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