在 monad 转换器中使用类型同义词

发布于 2024-09-12 20:56:11 字数 1078 浏览 5 评论 0原文

是否可以使用类型同义词作为 monad 转换器类型构造函数的参数?特别是,如果应用的 monad 转换器有一个一元类型同义词,它是否可以用作另一个 monad 转换器中底层 monad 的类型?

据我所知,类型同义词不被接受为一流类型构造函数,请参阅下面的示例和错误消息:

-- Using type synonym of a monad transformer in another monad transformer.

import Control.Monad.Reader

-- inner transformer
type A a = ReaderT Int IO a

-- type B a = ReaderT String A a
{- Error:
readert2.hs:8:0:
    Type synonym `A' should have 1 argument, but has been given 0
    In the type synonym declaration for `B'
-}

-- type B a = ReaderT String (A a) a
{- Error:
readert2.hs:15:27:
    Kind mis-match
    The second argument of `ReaderT' should have kind `* -> *',
    but `A a' has kind `*'
    In the type `ReaderT String (A a) a'
    In the type synonym declaration for `B'
-}

type B a = ReaderT String (ReaderT Int IO) a
{- OK -}

main = do
  r <- flip runReaderT 39 $ do
          n <- ask :: A Int
          s <- flip runReaderT "foo" $ (ask :: B String)
          return $ n + length s
  print r

有没有办法避免在 B a 的定义中扩展类型同义词 A

Is it possible to use type synonyms as arguments of monad transformers' type constructor? In particular, if there is an unary type synonym for an applied monad transformer, could it be used as a type of the underlying monad in another monad transformer?

From what I see type synonyms are not accepted as first-class type constructors, see example and error messages below:

-- Using type synonym of a monad transformer in another monad transformer.

import Control.Monad.Reader

-- inner transformer
type A a = ReaderT Int IO a

-- type B a = ReaderT String A a
{- Error:
readert2.hs:8:0:
    Type synonym `A' should have 1 argument, but has been given 0
    In the type synonym declaration for `B'
-}

-- type B a = ReaderT String (A a) a
{- Error:
readert2.hs:15:27:
    Kind mis-match
    The second argument of `ReaderT' should have kind `* -> *',
    but `A a' has kind `*'
    In the type `ReaderT String (A a) a'
    In the type synonym declaration for `B'
-}

type B a = ReaderT String (ReaderT Int IO) a
{- OK -}

main = do
  r <- flip runReaderT 39 $ do
          n <- ask :: A Int
          s <- flip runReaderT "foo" $ (ask :: B String)
          return $ n + length s
  print r

Is there a way to avoid expanding the type synonym A in the definition of B a?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

满地尘埃落定 2024-09-19 20:56:11

类型同义词不能部分应用。在这种特定情况下,您可以编写

type A = ReaderT Int IO
type B a = ReaderT String A a

[或者甚至更好的 type B = ReaderT String A 以在另一个 monad 转换器中使用 B]

一般而言,如果不使用 newtype 则不可能进行转换/data,例如:

type A a = Reader a Int

不能等效地写为type A = ...。从某种意义上说,此功能相当于类型级别的 lambda \a ->读取一个 Int

Type synonyms cannot be partially applied. In this specific case, you can write

type A = ReaderT Int IO
type B a = ReaderT String A a

[or even better type B = ReaderT String A to use B in another monad transformer]

It's general, that transformation is impossible without using newtype/data, for example:

type A a = Reader a Int

cannot be equivalently written as type A = .... In some sense, this feature would be equivalent to type-level lambda \a -> Reader a Int.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文