我正在尝试构建一个函数,该函数从列表中返回单个元素。该列表是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
非常感谢任何帮助!
答案 0 :(得分:2)
我将从您的规范中翻译出来:
如果列表中没有元素,我想返回错误。
f [] = mzero
如果 list只包含1个元素,我想将该元素作为一个返回 单子。
f [x] = return x
如果列表包含多个元素,我想返回一个 错误。
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
答案 1 :(得分:1)
首先,hoogle是你的朋友。您可以查找签名,发现getFirst
只是fst
,getSecond
是snd
,您getValue
的实现可以写为fromMaybe false
}。
就错误消息而言,value
的类型为(Integral i) => Maybe i
(或接近,我现在没有编译器),这是{{1}的一个可能值返回。但签名singleElemOnly
表示必须返回调用者想要的任何 (MonadPlus m) => [a] -> m a
。
同样,如果您在GHCi中运行此功能,则MonadPlus
的类型默认为test2
,但Maybe (Integer, [Integer])
必须能够返回任何 { {1}}输入。