我对Haskell很陌生,并且不完全了解Maybe monads。
data Hmm = Hmm [Maybe Int]
deriving (Show, Eq)
yd = Hmm [Just 8, Just 5,Nothing,Just 2, Nothing, Just 2, Nothing,Nothing]
getVal = case yd of
[Just val] -> putStr val
[Nothing] -> putStr "."
我想通过用点替换Nothing和用n替换n(全部在一行中)来提取我的列表。但是,这段代码给了我一个错误。
Couldn't match expected type "Hmm" with actual type '[Maybe a0]'
In the pattern : [Nothing]
In a case alternative: [Nothing] -> putStr "."
In the expression:
case yd of
[Just val] -> putStr val
[Nothing] -> putStr "."
基本上我希望上面的列表采用格式" 85.2.2 .."
答案 0 :(得分:3)
错误消息告诉您错误:
无法将预期类型“Hmm”与实际类型'[Maybe a0]'
匹配
让我们使用[Int]
而不是[Maybe Int]
进行简化,这样我们就可以将monad完全从图片中删除。让我们使用0
代替Nothing
和x
代替Just x
重新编写您的测试用例
data Hmm = Hmm [Int]
deriving (Show, Eq)
yd = Hmm [8, 5, 0, 2, 0, 2, 0, 0]
getVal = case yd of
[0] -> putStr "."
[x] -> putStr $ show x
-- N.B. I had to reverse the order here since `[x]` will match before `[0]`.
-- This isn't an issue when you're still using Maybes, since Just x doesn't match Nothing
现在我们根本没有任何monadic元素(除了getVal :: Hmm -> IO ()
,但是......),你仍然会遇到和以前一样的问题。 yd
被构建为Hmm
,但您在其上唯一匹配的模式是查找[a]
。此外,两种模式仅查找单元素列表,因此即使yd :: [Int]
也不匹配。
让我们在模式匹配中使用Hmm
构造函数重写并正确递归以捕获整个列表。我们还会重新编写getVal
以返回String
,因此我们甚至不必弄乱IO
返回的putStr :: String -> IO ()
monad。
import Data.Char (intToDigit)
data Hmm = Hmm [Int]
deriving (Show, Eq)
yd = Hmm [8, 5, 0, 2, 0, 2, 0, 0]
getVal :: Hmm -> String
getVal (Hmm []) = []
getVal (Hmm (0:xs) = '.' : getVal (Hmm xs)
getVal (Hmm (x:xs) = intToDigit x : getVal (Hmm xs)
result :: String
result = getVal yd
注意我在模式匹配中如何包含三个替换。一个用于Hmm []
- 包含在Hmm
类型中的空列表,一个用于Hmm (0:xs)
的空列表 - 由Hmm
包装的非空列表,其第一个值为零,和Hmm (x:xs)
一个 - 由Hmm
包装的非空列表,每个结果但第一个是递归的。这将返回:
getVal yd =
getVal (Hmm (8:[5, 0, 2, 0, 2, 0, 0])) =
'8' : getVal (Hmm (5: [0, 2, 0, 2, 0, 0])) =
'8':'5' : getVal (Hmm (0: [2, 0, 2, 0, 0])) =
'8':'5':'.' : getVal (Hmm (2: [0, 2, 0, 0])) =
'8':'5':'.':'2' : getVal (Hmm (0: [2, 0, 0])) =
'8':'5':'.':'2':'.' : getVal (Hmm (2: [0, 0])) =
'8':'5':'.':'2':'.':'2' : getVal (Hmm (0: [0])) =
'8':'5':'.':'2':'.':'2':'.' : getVal (Hmm (0:[])) =
'8':'5':'.':'2':'.':'2':'.':'.': getVal (Hmm []) = -- base case!
'8':'5':'.':'2':'.':'2':'.':'.':[] = -- re-write as list
['8', '5', '.', '2', '.', '2', '.', '.'] -- re-write as String
"85.2.2.."
请注意这只是:
toString :: Hmm -> String
toString (Hmm xs) = map f xs where
f 0 = '.'
f x = intToDigit x
要在此处使用Maybe Int
并将其返回到monad世界,只需对代码应用相同的更改
import Data.Char (intToDigit)
data Hmm = Hmm [Maybe Int]
deriving (Show, Eq)
yd = Hmm [Just 8, Just 5, Nothing, Just 2, Nothing, Just 2, Nothing, Nothing]
getVal :: Hmm -> String
getVal (Hmm []) = []
getVal (Hmm (Nothing:xs)) = '.' : getVal (Hmm xs)
getVal (Hmm (Just x :xs)) = intToDigit x : getVal (Hmm xs)
-- or equivalently
getVal' :: Hmm -> String
getVal' (Hmm xs) = map f xs where
f Nothing = '.'
f (Just x) = intToDigit x