The most direct way is to just do it by hand:
fromList :: [Double] -> Maybe OrbitElements
fromList [ _epoch
, _ecc
, _distPeri
, _incl
, _longAscNode
, _argPeri
, _timePeri
, _meanMotion
, _meanAnomaly
, _trueAnomaly
, _semiMajorAxis
, _distApo
, _period
]
= Just $ OrbitElements
_epoch
_ecc
_distPeri
_incl
_longAscNode
_argPeri
_timePeri
_meanMotion
_meanAnomaly
_trueAnomaly
_semiMajorAxis
_distApo
_period
fromList _ = Nothing
However, there is a slightly sexier way, which is to parse them element by element, which is less error-prone and more descriptive of what we are trying to do:
First we define two parsers, one of which requests a new element from the list (or fails if the list is empty), and the second of which matches the end of the list (or fails if the list is not empty):
import Control.Applicative
import Control.Monad
import Control.Monad.Trans.State
getElem :: StateT [Double] Maybe Double
getElem = do
s <- get
case s of
[] -> mzero
x:xs -> do
put xs
return x
endOfList :: StateT [Double] Maybe ()
endOfList = do
s <- get
case s of
[] -> return ()
_ -> mzero
Now we can define fromList
in Applicative style:
fromList' :: [Double] -> Maybe OrbitElements
fromList' = evalStateT $ OrbitElements
<$> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<*> getElem
<* endOfList