Initializing algebraic data type from list
algebraic-data-types, haskell, list
Solution
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
Problem
I'm a fairly new Haskell programmer and I'm trying to figure out how to get some values into an algebraic data type. I have a record data type: ``` data OrbitElements = OrbitElements { epoch :: Double, ecc :: Double, distPeri :: Double, incl :: Double, longAscNode :: Double, argPeri :: Double, timePeri :: Double, meanMotion :: Double, meanAnomaly :: Double, trueAnomaly :: Double, semiMajorAxis :: Double, distApo :: Double, period :: Double } ``` I'm pulling in some info from a text file, which ends up in a list of Doubles. Is there an easy way to initialize this data type with the list? I could just call each setter individually but that seems terribly inefficient when I already have all the values in a list. ``` let d = [2456382.5,6.786842103348031e-3,0.7184187640759256,3.394660181513041,76.64395338801751,55.2296201483587,2456457.141012543,1.602144936476915,240.4142797010899,239.7408018186761,0.7233278761603762,0.7282369882448266,224.6987721295883] let o = OrbitElements let epoch o = d !! 0 let ecc o = d !! 1 -- and so on ``` What am I missing?