[英]Inferred type is ambiguous
I'm trying to build a library to fill in a template based on some context. 我正在尝试建立一个库来基于某些上下文填充模板。
The relevant data types are a ContextNode
and Context
. 相关的数据类型是
ContextNode
和Context
。
data ContextNode m = ContextText Text
| ContextSub (Context m)
type Context m = (Text -> m (Maybe (ContextNode m)))
I defined a typeclass ContextGenerator
to be able to derive something context like for data types using generics. 我定义了一个类型类
ContextGenerator
,以便能够使用泛型派生某种类似于数据类型的上下文。
class ContextGenerator m a where
clookup :: a -> Text -> m (Maybe (ContextNode m))
Context
should be an instance of ContextGenerator
Context
应该是ContextGenerator
的实例
instance (MonadIO m) => ContextGenerator m (Context m) where
clookup a s = a s
Some code to make contexts 一些代码来制作上下文
mkContext :: MonadIO m => Text -> ContextNode m -> Context m
mkContext s n = \s' -> if s' == s then return (Just n) else return Nothing
The thing that isn't working is when I do the following (in repl where I enabled OverloadedStrings and FlexibleContexts) 不起作用的是当我执行以下操作(在repl中,我启用了OverloadedStrings和FlexibleContexts)
> let ctx = mkContext "hello" (ContextText "world")
> clookup ctx "hello"
Could not deduce (Control.Monad.IO.Class.MonadIO m0)
from the context (Control.Monad.IO.Class.MonadIO m1,
ContextGenerator m (Context m1))
bound by the inferred type for ‘it’:
(Control.Monad.IO.Class.MonadIO m1,
ContextGenerator m (Context m1)) =>
m (Maybe (ContextNode m))
at <interactive>:18:1-19
The type variable ‘m0’ is ambiguous
When checking that ‘it’ has the inferred type
it :: forall (m :: * -> *) (m1 :: * -> *).
(Control.Monad.IO.Class.MonadIO m1,
ContextGenerator m (Context m1)) =>
m (Maybe (ContextNode m))
Probable cause: the inferred type is ambiguous
It seems to me that the GHC infers that the two m
's in the instance definition are different, is that correct? 在我看来,GHC推断实例定义中的两个
m
是不同的,对吗? How can I tell GHC that these should be the same? 我怎样才能告诉GHC这些应该是相同的?
You can make this work using functional dependencies in GHC - just add the language-extension and rewrite your type-class to: 您可以使用GHC中的功能依赖项来完成这项工作-只需添加语言扩展并将类型类重写为:
class ContextGenerator m a | a -> m where ...
this basically says that a
should include the choice for m
(you could say ContextGenerator
is now not a binary relation for the types m
and a
but a function from a -> m
- which is implied by the syntax of the extension too) 这基本上说
a
应该包括对m
的选择(您可以说ContextGenerator
现在不是类型m
和a
的二进制关系,而是ContextGenerator
a -> m
的函数,扩展语法也暗含了该函数)
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
import Data.Text
import Control.Monad.IO.Class
data ContextNode m = ContextText Text
| ContextSub (Context m)
type Context m = (Text -> m (Maybe (ContextNode m)))
class ContextGenerator m a | a -> m where
clookup :: a -> Text -> m (Maybe (ContextNode m))
instance (MonadIO m) => ContextGenerator m (Context m) where
clookup a s = a s
mkContext :: MonadIO m => Text -> ContextNode m -> Context m
mkContext s n = \s' -> if s' == s then return (Just n) else return Nothing
λ> let ctx = mkContext "hello" (ContextText "world")
λ> (Just (ContextText t)) <- clookup ctx "hello"
λ> t
"world"
λ> Just _ <- clookup ctx "???"
*** Exception: user error (Pattern match failure in do expression at <interactive>:41:1-6)
λ> Nothing <- clookup ctx "???"
(...empty of course...)
as those types and classes are dependent of each other I am unsure that you really have a use-case for the type-class here- maybe you would be fine with just the function without all the overhead instead? 因为这些类型和类彼此依赖,所以我不确定您在这里确实有一个类型类用例-也许只使用函数而没有所有开销就可以了吗?
{-# LANGUAGE OverloadedStrings #-}
import Data.Text
import Control.Monad.IO.Class
clookup :: Context m -> Text -> m (Maybe (ContextNode m))
clookup a s = a s
data ContextNode m
= ContextText Text
| ContextSub (Context m)
type Context m = (Text -> m (Maybe (ContextNode m)))
mkContext :: MonadIO m => Text -> ContextNode m -> Context m
mkContext s n = \s' -> if s' == s then return (Just n) else return Nothing
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.