【问题标题】:Keep getting (Use FlexibleContexts to permit this) Error In Simple Haskell Function在简单的 Haskell 函数中不断出现(使用 FlexibleContexts 来允许这样做)错误
【发布时间】:2017-04-06 01:41:32
【问题描述】:

我只是在玩 Haskell monads,但我不断收到一个似乎无法修复的错误。我的代码段使用状态 Monad 将字符串中的前两个字符加在一起并将它们作为状态的一部分返回。我的“put”行不断给我错误:

* Non type-variable argument in the constraint: MonadState [a] m
  (Use FlexibleContexts to permit this)
* When checking the inferred type
    testH :: forall (m :: * -> *) a. MonadState [a] m => [a] -> m [a]

我该如何解决这个问题?扩展语言不是一种选择,我只需要知道如何更改我的代码以使其工作

test xs = 
 runState (testH (tail xs)) ((head xs):[])

testH xs =
 do
  a <- get 
  put ((head xs):a)
  b <- get
  return b

【问题讨论】:

  • 你在导入Control.Monad.State吗?如果是这样,请尝试导入 Control.Monad.Trans.State
  • 我不完全确定我明白您所说的“扩展语言不是一种选择”是什么意思。如果您只是在玩 monad,为什么不在代码顶部添加 {-# LANGUAGE FlexibleContexts #-}
  • “扩展语言不是一种选择”,除非您使用MultiParamTypeClasses,只是在范围内包含MonadState,因此已经扩展了语言。

标签: haskell monads state-monad


【解决方案1】:

您可以通过启用FlexibleContexts 来解决此问题,如它所建议的那样,或者通过更改您的函数来处理比列表更通用的东西。

问题是 Haskell 不允许在上下文中使用非类型变量的东西。如果你写出你的函数的类型(你应该这样做),你会得到

testH :: (Monad m,MonadState [a] m) => [a] -> m [a]

这意味着它是一个函数,它接受一个值列表并在某个 monad 中返回一个动作,该动作能够保持与输入相同类型的值列表的状态。不幸的是,上下文中的 [a] 位是无效的 Haskell,因为它有一个非类型变量的东西(即列表类型构造函数)。

这里最好的解决方案是只启用扩展,它允许上下文中的非类型变量。这并不危险,它只是放宽了标准。事实上,多参数类型类(如MonadState)不是有效的Haskell,所以不管你喜欢与否,你已经在使用语言扩展了。

如果这确实不是一个选项,您可以将其更改为(Monad m,SomeTypeclass f,MonadState (f a) m),并重写您的函数以使用任何遵循您选择的SomeTypeclass 的构造函数。这会从类型中删除列表类型构造函数,并允许代码在没有FlexibleContexts 的情况下工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-24
    • 2017-03-21
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多