我正在玩Haskell monad并且我一直在收到一个我似乎无法解决的错误。我的代码段使用状态Monad将字符串中的前两个字符添加到一起,并将它们作为状态的一部分返回。我的"放" line一直给我错误:
* 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
答案 0 :(得分: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
的情况下工作。