2017-04-06 66 views
2

我只是哈斯克尔单子玩弄和我不断收到,我似乎无法修复的错误。我的代码段使用状态Monad将字符串中的前两个字符添加到一起,并将它们作为状态的一部分返回。我的“放”行不断给我的错误:也能收到(使用FlexibleContexts允许此)错误在简单的Haskell功能

* 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

你导入'Control.Monad.State'?如果是这样,请尝试导入“Control.Monad.Trans.State”。 – Alec

+1

我并不完全相信,我知道你的意思是“扩展语言不是一种选择”。如果你只是在玩monads,为什么不在你的代码的顶部添加'{ - #LANGUAGE FlexibleContexts# - }'? – Lazersmoke

+0

“扩展的语言是不是一种选择”,除非你正在使用'MultiParamTypeClasses'单单是'MonadState'的范围,因此已经扩展了语言。 –

回答

0

因为它表明您可以通过启用FlexibleContexts解决这个问题,或者通过更改功能工作比列表更普遍。

的问题是,哈斯克尔不允许在上下文非类型变量的东西。如果你写出来你的函数类型(你本来也应该这样做),你会得到

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

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

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

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

相关问题