【问题标题】:How can I give this sub-function an explicit type?我怎样才能给这个子函数一个明确的类型?
【发布时间】:2012-09-21 12:46:52
【问题描述】:

我有以下haskell代码来扩展字符串中的环境变量(解析代码省略):

import Control.Monad (liftM)

data Token = Literal String | EnvReference String deriving Show

expandTokens :: (Monad m) => (String -> m (Maybe String)) -> [Token] -> m String
expandTokens getEnv toks = liftM concat (mapM toString toks) where
    toString (Literal s) = return s
    toString (EnvReference v) = liftM (maybe "" id) (getEnv v)

(它打算与 getEnv 的 IO 实现一起使用,但我认为如果可以与任何 monad 一起使用它会更好地进行测试)

当我写它的时候,我试图给嵌套的toString函数一个明确的类型:

toString :: Monad m => Token -> m String

但是 ghc 说:

Sample.hs:8:58:
    Could not deduce (m ~ m1)
    from the context (Monad m)
      bound by the type signature for
                 expandTokens :: Monad m =>
                                 (String -> m (Maybe String)) -> [Token] -> m String
( ... )

我知道 expandTokens 中的“Monad m”必须与 toString 类型中的 m 完全相同(因为它引用了包含函数的 getenv),但我不能弄清楚如何为 toString 编写一个明确的类型,它尊重这一点 - 我认为没有任何方法可以在不同的类型声明中引用任何内容,甚至可以做到吗?

【问题讨论】:

  • 啊,真的 - 我真的不知道要搜索什么才能找到骗子。这是一条不同的错误消息,但它看起来是相同的。
  • @dave4420:我认为相同的原因和解决方案,并不是同一个问题。

标签: haskell types typeclass


【解决方案1】:

我认为您正在寻找ScopedTypeVariables。我从来没有用过,但它看起来不错。

【讨论】:

  • 就是这个,谢谢!然后变成:expandTokens :: forall m . (Monad m) => (String -> m (Maybe String)) -> [Token] -> m String
  • @gfxmonk:另外,注意Monad 约束也是可见的,所以你不需要toString 类型的约束。
猜你喜欢
  • 2018-03-25
  • 2011-04-27
  • 2021-10-06
  • 2023-02-05
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2021-09-24
  • 1970-01-01
相关资源
最近更新 更多