Haskell将Maybe转换为已定义的Type

Vir*_*igy 0 haskell

我在学习Haskell的前几天,我正在努力处理Maybe 从Haskell find函数返回的类型.我定义了一个函数FindNextState,它接受一个元组和2个字符串.这个函数调用getListOfNextStates使用lambda和模式匹配来从传入的元组中获取列表,然后使用find函数的谓词我在该列表中找到匹配项.问题是find返回返回Maybe我的Transition类型,这阻止我调用我的getToState函数,因为它期望在Transition.无论如何转换Maybe由find函数返回?

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
Run Code Online (Sandbox Code Playgroud)

样本输入

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

*Main> :t findNextState dfa "s2" "0"
findNextState dfa "s2" "0" :: Maybe Transisition
Run Code Online (Sandbox Code Playgroud)

**所需代码**

findNextState :: DFA -> State -> Symbol -> State
findNextState (_,_,_,tList) state symbol = getToState( (getListOfNextStates tList state symbol) )
Run Code Online (Sandbox Code Playgroud)

Dar*_*nec 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
Run Code Online (Sandbox Code Playgroud)

或者更简洁,您可以使用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
Run Code Online (Sandbox Code Playgroud)

如果你真的不认为会有失败的发现,或者你只是不在乎,你可以使用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)
Run Code Online (Sandbox Code Playgroud)

这将在getListOfNextStates返回时抛出异常Nothing,从而有效地使程序崩溃.我不会在实际代码中执行此操作,除非您绝对可以确保它永远不会发生.