我有一个代数数据类型:
data Toll = Vok Int Bool | Bok Int | Cokd String Char
和另一个功能
getVal :: Int -> Toll
getVal 1 = Cokd "hello" 'c'
getVal _ = Bok 12
我想在某些功能中调用getVal
并提取Cokd
的参数(如果答案为类型Cokd
)(也许使用模式匹配)。
我可以喜欢:
hello :: Int -> Bool
hello x = if st == "hell" then True else False
where (Cokd st ch) = getVal x
我不能使用单子。
如何做?
您可以使用 case
进行模式匹配getVal
的结果:
data Toll = Vok Int Bool | Bok Int | Cokd String Char
getVal :: Int -> Toll
getVal 1 = Cokd "hello" 'c'
getVal _ = Bok 12
hello :: Int -> Bool
hello x =
case getVal x of
Cokd st ch ->
st == "hell"
_ -> False
或创建一个单独的函数和模式与参数匹配:
hello :: Int -> Bool
hello =
helloToll . getVal
where
helloToll (Cokd st ch) = st == "hell"
helloToll _ = False
您在问题编译中提供的示例(几乎没有修改),但是当您尝试使用2
调用hello
(或与1
不同的任何其他值时,它将引发运行时异常,在这种情况下,getValue
返回Bok 12
,因此(Cokd st ch) = getVal x
无法进行模式匹配)。
您的代码看起来完全不错,只有一个更正:模式if <expr> then True else False
可以用<expr>
替换。
hello :: Int -> Bool
hello x = st == "hell" where (Cokd st ch) = getVal x
但是,由于非排量模式匹配,此代码将因1
以外的值而失败。您需要涵盖所有案例:
hello :: Int -> Bool
hello x = case getVal x of
Cokd st ch -> st == "hell"
_ -> False