Haskell将Maybe转换为定义的类型

时间:2018-10-09 22:35:45

标签: haskell

我正处于学习Haskell的前几天,我正为从Haskell的Maybe函数返回的find类型而苦恼。我定义了一个名为FindNextState的函数,它接收一个元组和2个字符串。此函数调用getListOfNextStates,该函数使用lambda和模式匹配从传入的元组中获取列表,然后使用find函数的谓词在该列表中找到匹配项。问题是查找返回返回我的Transition类型的Maybe,这使我无法调用我的getToState函数,因为它期望在Transition上进行。无论如何,是否可以转换由find函数返回的Maybe

代码

type State = String
type Symbol = String
type Transisition = (State, Symbol, State)

states = ["s0","s1"]
initState = "s0"
finalStates = ["s3"]
transisitionList = [("s0", "0", "s1"), ("s0", "1", "s1")]
dfa = (states, initState, finalStates, transisitionList)

getToState :: Transisition -> State
getToState  (_, _, toState) = toState


findNextState :: DFA -> State -> Symbol -> Maybe Transisition --Maybe Transisition is the issue, I need it to be my type of Transisition otherwise Haskell throws an error when I load my program 
findNextState (_,_,_,tList) state symbol =  getListOfNextStates tList state symbol

getListOfNextStates :: [Transisition] -> State -> Symbol -> Maybe Transisition
getListOfNextStates tList state symbol = find(\(sState,sym,eState) -> matchTransition state symbol (sState,sym,eState)) tList

样本输入

findNextState dfa "s2" "0"
Just ("s2","0","s3")

*Main> :t findNextState dfa "s2" "0"
findNextState dfa "s2" "0" :: Maybe Transisition

**所需代码**

findNextState :: DFA -> State -> Symbol -> State
findNextState (_,_,_,tList) state symbol = getToState( (getListOfNextStates tList state symbol) )

1 个答案:

答案 0 :(得分:7)

我建议保留Maybe,因为如果找不到匹配项,它会使代码正常失败。如果这样做,您将使getListOfNextStates返回Maybe Transition,然后将findNextState更改为返回Maybe State。现在,您可以像这样定义它:

findNextState :: DFA -> State -> Symbol -> Maybe State
findNextState (_,_,_,tList) state symbol = case newstate of
    Just s -> Just (getToState s)
    Nothing -> Nothing
  where newstate = getListOfNextStates tList state symbol

或更简洁地说,您可以像这样使用fmap :: (a -> b) -> Maybe a -> Maybe b(或其中缀版本<$>):

findNextState :: DFA -> State -> Symbol -> Maybe State
findNextState (_,_,_,tList) state symbol = getToState <$> newstate
  where newstate = getListOfNextStates tList state symbol

如果您真的不认为查找失败,或者您根本不在乎,可以使用fromJust :: Maybe Transition -> Transition,如下所示:

import Data.Maybe

getListOfNextStates :: [Transisition] -> State -> Symbol -> Transisition
getListOfNextStates tList state symbol = fromJust (find (\(sState,sym,eState) -> matchTransition state symbol (sState,sym,eState)) tList)

如果getListOfNextStates返回Nothing,这将引发异常,从而实际上导致程序崩溃。除非您可以绝对确保它永远不会发生,否则我不会在真实代码中这样做。