Haskell 无法理解monad的错误处理
我试图构建一个函数,从列表中返回单个元素。该列表是Haskell 无法理解monad的错误处理,haskell,monads,monadplus,Haskell,Monads,Monadplus,我试图构建一个函数,从列表中返回单个元素。该列表是Maybe(Int,[Int])tupel的一部分 如果列表不包含任何元素,我想返回一个错误。 如果列表正好包含1个元素,我想将该元素作为Monad返回。 如果列表包含多个元素,我想返回一个错误 我有点迷路了,看不出如何让这件相当简单的事情起作用。 以下是我到目前为止的情况: import Control.Monad test1 = Just (1,[2,3]) :: Maybe (Int,[Int]) test2 = Just (2,[1])
Maybe(Int,[Int])
tupel的一部分
如果列表不包含任何元素,我想返回一个错误。
如果列表正好包含1个元素,我想将该元素作为Monad返回。
如果列表包含多个元素,我想返回一个错误
我有点迷路了,看不出如何让这件相当简单的事情起作用。
以下是我到目前为止的情况:
import Control.Monad
test1 = Just (1,[2,3]) :: Maybe (Int,[Int])
test2 = Just (2,[1]) :: Maybe (Int,[Int])
test3 = Just (3,[]) :: Maybe (Int,[Int])
getValue :: Maybe Bool -> Bool
getValue (Just x) = x
getValue Nothing = False
singleElemOnly :: (MonadPlus m) => [a] -> m a
singleElemOnly x = let result = test2
value = fmap fst result
isEmpty = fmap null (fmap snd result)
in if (getValue isEmpty) then value else mzero
不幸的是,作为一个初学者,我在试图编译这篇文章时收到的错误消息对我来说毫无用处
Playground.hs:15:50:
Could not deduce (a ~ Int)
from the context (MonadPlus m)
bound by the type signature for
singleElemOnly :: MonadPlus m => [a] -> m a
at Playground.hs:11:19-45
`a' is a rigid type variable bound by
the type signature for singleElemOnly :: MonadPlus m => [a] -> m a
at Playground.hs:11:19
Expected type: m a
Actual type: Maybe Int
Relevant bindings include
x :: [a]
(bound at Playground.hs:12:16)
singleElemOnly :: [a] -> m a
(bound at Playground.hs:12:1)
In the expression: value
In the expression: if (getValue isEmpty) then value else mzero
Playground.hs:15:50:
Could not deduce (m ~ Maybe)
from the context (MonadPlus m)
bound by the type signature for
singleElemOnly :: MonadPlus m => [a] -> m a
at Playground.hs:11:19-45
`m' is a rigid type variable bound by
the type signature for singleElemOnly :: MonadPlus m => [a] -> m a
at Playground.hs:11:19
Expected type: m a
Actual type: Maybe Int
Relevant bindings include
singleElemOnly :: [a] -> m a
(bound at Playground.hs:12:1)
In the expression: value
In the expression: if (getValue isEmpty) then value else mzero
非常感谢任何帮助 首先,是你的朋友。您可以查找签名,发现getFirst
只是fst
,getSecond
是snd
,并且getValue
的实现可以写成fromFalse
就错误消息而言,value
的类型为(积分i)=>可能是i
(或者类似的,我现在没有编译器),这是singleElemOnly
返回的一个可能值。但是签名(MonadPlus m)=>[a]->ma
表示它必须返回调用方想要的任何MonadPlus
类似地,如果您在GHCi中运行此操作,则
test2
的类型默认为Maybe(Integer,[Integer])
,但是singleElemOnly
必须能够返回任何积分类型。我将从您的规范转换为:
如果列表不包含任何元素,我想返回一个错误
如果
列表正好包含1个元素,我想将该元素作为
蒙纳德
如果列表包含多个元素,我想返回一个
错误
所以,把一切放在一起:
singleElemOnly :: (MonadPlus m) => [a] -> m a
singleElemOnly [] = mzero
singleElemOnly [x] = return x
singleElemOnly _ = mzero
-- a _ catches everything else, no need to write the exact pattern
或者更简单地说,因为第三种情况包括第一种情况:
singleElemOnly :: (MonadPlus m) => [a] -> m a
singleElemOnly [x] = return x
singleElemOnly _ = mzero
错误消息是什么?总是发布你看到的编译器错误。抱歉,错误太长了。我添加了它们并修复了这个示例。将类型签名添加到test1,
:您可能希望它们的类型为Maybe(Int,[Int])
或类似的类型。GHC为您选择了Integer
而不是Int
。一旦该类型被修复,您现在可以看到您的函数singleelemony
只返回Int/Integer
类型,而它的签名保证它可以在任何类型a
下工作(而不仅仅是Int
)。这是GHC报告的类型错误。此外,我不清楚上一个函数应该做什么。你能编辑你的问题来解释你想要达到的目标吗?我现在的猜测是f[]=mzero;f(x:uz)=返回x
但很难说。@chi抱歉,我用最新的代码和错误更新了问题,并对我想要实现的目标进行了更好的解释。这几乎是完美的!但现在我需要以某种方式将test1
作为一个参数引入其中,而这一部分我仍然无法理解singleElemOnly(fmap snd test2)
不起作用,它抱怨它“无法将类型可能与[]
匹配”?singleElemOnly
获取一个列表<代码>fmap snd测试
具有类型可能[Int]
。您可以执行fmap(singleElement.snd)测试
,但这会得到可能(可能[Int])
。您可能希望fmap snd test>=singleElement
。
f (_:_:_) = mzero
singleElemOnly :: (MonadPlus m) => [a] -> m a
singleElemOnly [] = mzero
singleElemOnly [x] = return x
singleElemOnly _ = mzero
-- a _ catches everything else, no need to write the exact pattern
singleElemOnly :: (MonadPlus m) => [a] -> m a
singleElemOnly [x] = return x
singleElemOnly _ = mzero