无法理解 monad 的错误处理
Trouble understanding error handling with monads
我正在尝试构建一个函数,该函数 return 将我作为列表中的单个元素。该列表是 Maybe (Int,[Int])
元组的一部分。
如果列表不包含任何元素,我想return报错。
如果列表恰好包含 1 个元素,我想 return 该元素作为 Monad。
如果列表包含超过 1 个元素,我想 return 一个错误。
我有点迷茫,看不出如何让这个相当简单的东西发挥作用。
这是我目前所拥有的:
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
非常感谢任何帮助!
首先,hoogle是你的朋友。您可以查找签名,发现 getFirst
只是 fst
,getSecond
是 snd
,而您实现的 getValue
可以写成 fromMaybe false
.
就错误消息而言,value
的类型为 (Integral i) => Maybe i
(或类似的东西,我现在没有编译器),这是 [=18] 的一个可能值=] return秒。但是签名 (MonadPlus m) => [a] -> m a
说它必须 return any MonadPlus
调用者想要的。
同理,如果你在GHCi中是运行这个,那么test2
的类型默认为Maybe (Integer, [Integer])
,但是singleElemOnly
必须能够return 任何 Integral
类型。
我会根据您的说明进行翻译:
If the list contains no elements, I want to return an error.
f [] = mzero
If the
list contains exactly 1 element, I want to return that element as a
Monad.
f [x] = return x
If the list contains more than 1 element, I want to return an
error.
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
我正在尝试构建一个函数,该函数 return 将我作为列表中的单个元素。该列表是 Maybe (Int,[Int])
元组的一部分。
如果列表不包含任何元素,我想return报错。 如果列表恰好包含 1 个元素,我想 return 该元素作为 Monad。 如果列表包含超过 1 个元素,我想 return 一个错误。
我有点迷茫,看不出如何让这个相当简单的东西发挥作用。 这是我目前所拥有的:
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
非常感谢任何帮助!
首先,hoogle是你的朋友。您可以查找签名,发现 getFirst
只是 fst
,getSecond
是 snd
,而您实现的 getValue
可以写成 fromMaybe false
.
就错误消息而言,value
的类型为 (Integral i) => Maybe i
(或类似的东西,我现在没有编译器),这是 [=18] 的一个可能值=] return秒。但是签名 (MonadPlus m) => [a] -> m a
说它必须 return any MonadPlus
调用者想要的。
同理,如果你在GHCi中是运行这个,那么test2
的类型默认为Maybe (Integer, [Integer])
,但是singleElemOnly
必须能够return 任何 Integral
类型。
我会根据您的说明进行翻译:
If the list contains no elements, I want to return an error.
f [] = mzero
If the list contains exactly 1 element, I want to return that element as a Monad.
f [x] = return x
If the list contains more than 1 element, I want to return an error.
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