首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AcidState函数中的模糊类型变量

AcidState函数中的模糊类型变量
EN

Stack Overflow用户
提问于 2013-02-06 04:42:54
回答 1查看 337关注 0票数 2

我在一个Haskell项目中遇到了一个情况,在那里我得到了错误Ambiguous type variable

相关代码是

代码语言:javascript
复制
--- Other import statements
import qualified Model as Model

---------- HTTP Handlers
needItem db user itemName = do
  Model.changeItemStatus db user itemName Model.Need
  listItems db user

gotItem db user itemName = do
  Model.changeItemStatus db user itemName Model.Got
  listItems db user

newItem db user itemName comment count = do
  Model.insertItem db user itemName comment count
  listItems db user

listItems db user = do
  lst <- Model.listItems db user
  resOk lst

--- rest of the program

这些错误都是针对insertItemchangeItemStatus的,它们都是acid-state查询函数。

代码语言:javascript
复制
insertItem db name itemName comment count = withAccount db name newItem
  where item = Item { itemName = itemName, itemComment = comment, itemCount = count, itemStatus = Need } 
        newItem account = update' db $ NewItem account item

-- other stuff

changeItemStatus db name itemName status = withAccount db name cItem
  where cItem account = withItem account itemName
                        (\i -> update' db $ ChangeItem account $ i { itemStatus = status})

withAccountwithItem是帮助我处理数据库中的Maybe返回值的辅助函数。他们被定义为

代码语言:javascript
复制
withAccount :: MonadIO m => AcidState GoGetDB -> String -> (Account -> a) -> m (Maybe a)
withAccount db name fn = do
  maybeAccount <- query' db $ AccountByName name
  return $ do acct <- maybeAccount
              return $ fn acct

withItem :: Account -> String -> (Item -> a) -> Maybe a
withItem account itemName fn = do
  item <- getOne $ (accountItems account) @= itemName
  return $ fn item

好吧,现在。

我已经读过几次快乐栈速成班中的AcidState文档,但是它没有多大帮助;它们在响应生成函数中直接使用查询

  • 我尝试并得到了相同的Ambiguous type variable错误,除了指向query'调用iteslf之外,
  • 我真的不想这么做,因为这会迫使我把我的模型/控制器代码和
  • 这无助于我的特殊情况,因为它没有告诉我调用query'update'的函数的具体返回类型是什么(它们的函数都是AcidState DBName -> ServerPart Response,因为它们直接生成响应)。

我试图在表达式的各个部分上使用insertItemchangeItemStatus的类型签名,但每次尝试都给了我一个假设,即No instance for (MonadIO m1)的错误更严重。

我还不是一个特别擅长Haskeller的人,所以我觉得我唯一能尝试的就是在这个地方随机地撒一些return $,但是听起来不太可能真的解决这个问题,或者教我任何东西。

我试图实现的一般概念是:“对DB进行此更改,然后返回当前用户的相关元素列表(可能发生更改)”。

对于我下一步该尝试什么,或者我具体出了什么问题,有什么暗示吗?我是不是用完全错误的方式想这件事?关于这个问题,我还有其他的文件可以参考吗?

PS。我已经包含了上面所有的相关代码,但是如果您想看到完整的源代码,那就是这里这里

编辑:全类型错误

代码语言:javascript
复制
/home/inaimathi/projects/goget/goget.hs:31:3:
    Ambiguous type variable `m2' in the constraint:
      (Control.Monad.IO.Class.MonadIO m2)
        arising from a use of `Model.changeItemStatus'
    Probable fix: add a type signature that fixes these type variable(s)
    In a stmt of a 'do' block:
      Model.changeItemStatus db user itemName Model.Need
    In the expression:
      do { Model.changeItemStatus db user itemName Model.Need;
           listItems db user }
    In an equation for `needItem':
        needItem db user itemName
          = do { Model.changeItemStatus db user itemName Model.Need;
                 listItems db user }

/home/inaimathi/projects/goget/goget.hs:35:3:
    Ambiguous type variable `m1' in the constraint:
      (Control.Monad.IO.Class.MonadIO m1)
        arising from a use of `Model.changeItemStatus'
    Probable fix: add a type signature that fixes these type variable(s)
    In a stmt of a 'do' block:
      Model.changeItemStatus db user itemName Model.Got
    In the expression:
      do { Model.changeItemStatus db user itemName Model.Got;
           listItems db user }
    In an equation for `gotItem':
        gotItem db user itemName
          = do { Model.changeItemStatus db user itemName Model.Got;
                 listItems db user }

/home/inaimathi/projects/goget/goget.hs:39:3:
    Ambiguous type variable `m0' in the constraint:
      (Control.Monad.IO.Class.MonadIO m0)
        arising from a use of `Model.insertItem'
    Probable fix: add a type signature that fixes these type variable(s)
    In a stmt of a 'do' block:
      Model.insertItem db user itemName comment count
    In the expression:
      do { Model.insertItem db user itemName comment count;
           listItems db user }
    In an equation for `newItem':
        newItem db user itemName comment count
          = do { Model.insertItem db user itemName comment count;
                 listItems db user }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-06 20:28:30

为您的函数编写类型签名,以捕获它们应该做的事情。在编写实现之前编写它们,然后可以使用类型签名,如果编译器知道您想要的类型,则可以从编译器获得更好的错误消息,以检查实现是否做了,或者至少有机会做您想做的事情。

让我们看看问题儿童,以及他们实际上做了什么:

acid-state中我们使用

代码语言:javascript
复制
update' :: (UpdateEvent event, MonadIO m) => AcidState (EventState event) -> event -> m (EventResult event)

代码语言:javascript
复制
insertItem db name itemName comment count = withAccount db name newItem
  where item = Item { itemName = itemName, itemComment = comment, itemCount = count, itemStatus = Need } 
        newItem account = update' db $ NewItem account item

现在让我们看看它会产生什么样的类型。从使用

代码语言:javascript
复制
withAccount :: MonadIO m => AcidState GoGetDB -> String -> (Account -> a) -> m (Maybe a)

我们看到结果有类型

代码语言:javascript
复制
m (Maybe a)

对于某些MonadIO manewItem的结果类型。现在,

代码语言:javascript
复制
newItem account = update' db something

所以

代码语言:javascript
复制
newItem :: MonadIO mio => Account -> mio (EventResult type_of_something)

因此,insertItem的结果类型应该是

代码语言:javascript
复制
m (Maybe (mio (EventResult type_of_something)))

和在

代码语言:javascript
复制
newItem db user itemName comment count = do
  Model.insertItem db user itemName comment count
  listItems db user

编译器不知道它应该在第二行中使用哪个MonadIO mio。因此,类型变量mio是不明确的。

请注意,在那里指定类型变量仍然不会做您想做的事情。我希望您实际上希望执行update',而不仅仅是计算在执行时更新数据库的操作。

对于insertItem来说,如果它确实应该更新数据库,那么现有的withAccount是没有用的。你也许需要一些东西

代码语言:javascript
复制
withAccountM :: MonadIO m => AcidState GoGetDB -> String -> (Account -> m a) -> m (Maybe a)
withAccountM db name fn = do
  maybeAccount <- query' db $ AccountByName name
  case maybeAccount of
    Nothing -> return Nothing
    Just acct -> do
         result <- fn acct
         return $ Just result

(没有测试,可能仍然是完全错误的)实际执行update'

对于changItemStatus,问题和可能的修复是相似的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14721720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档