Reputation: 1687
I'm in my first few days of learning Haskell and I'm struggle with the Maybe
type that is being returned from the Haskell's find
function. I defined a function called FindNextState
which takes in a tuple, and 2 Strings. This funcition calls getListOfNextStates
which uses a lambda and pattern matching to get a list from the passed in tuple and then uses the find
function's predicate I find a match in that list. The problem is find returns return a Maybe
of my Transition type, this is preventing me from calling my getToState
function because it's expecting at Transition. Is there anyway to convert the Maybe
returned by find function?
Code
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
Sample Input
findNextState dfa "s2" "0"
Just ("s2","0","s3")
*Main> :t findNextState dfa "s2" "0"
findNextState dfa "s2" "0" :: Maybe Transisition
** Desired Code**
findNextState :: DFA -> State -> Symbol -> State
findNextState (_,_,_,tList) state symbol = getToState( (getListOfNextStates tList state symbol) )
Upvotes: 1
Views: 2942
Reputation: 2778
I'd recommend keeping the Maybe
, as it allows the code to fail gracefully if it doesn't find a match. If you do that, you'll leave getListOfNextStates
returning Maybe Transition
, and then change findNextState
to return Maybe State
. Now you can define it like this:
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
Or more succinctly, you can use fmap :: (a -> b) -> Maybe a -> Maybe b
(or its infix version, <$>
) like so:
findNextState :: DFA -> State -> Symbol -> Maybe State
findNextState (_,_,_,tList) state symbol = getToState <$> newstate
where newstate = getListOfNextStates tList state symbol
If you really don't think there will be a failed find, or you just don't care, you can use fromJust :: Maybe Transition -> Transition
, like so:
import Data.Maybe
getListOfNextStates :: [Transisition] -> State -> Symbol -> Transisition
getListOfNextStates tList state symbol = fromJust (find (\(sState,sym,eState) -> matchTransition state symbol (sState,sym,eState)) tList)
This will throw an exception if getListOfNextStates
returns Nothing
, effectively crashing the program. I wouldn't do this in real code unless you can absolutely ensure that it will never happen.
Upvotes: 6