I want to get the Maybe parameters out of the Maybe wrapper
A wrapper that contains one or more approximation results
data CalculatedPoints =
Linear {xPoints :: [Maybe Double], yPoints :: [Maybe Double] }
| Segment {xPoints :: [Maybe Double], yPoints :: [Maybe Double]}
deriving Show
Trying to get values
main = do
resultPoints <- parseInput
case resultPoints of
[Nothing, Nothing] -> putStrLn "Calculation failed. Perhaps you did not specify a method."
[lpoints, Nothing] -> do
putStrLn "Linear Aproxiation"
let (xl, yl) = fromMaybe (Nothing, Nothing) lpoints -- THIS
-- prettyPoints xl yl
print $ xl
[Nothing, spoints] -> do
putStrLn "Segment Aproxiation"
print spoints
[lpoints, spoints] -> do
putStrLn "Linear Aproxiation"
print lpoints
putStrLn "Segment Aproxiation"
print spoints
I get this error
warning: [-Wdeferred-type-errors]
• Couldn't match type ‘CalculatedPoints’ with ‘(Maybe a, Maybe a1)
Expected: Maybe (Maybe a, Maybe a1) Actual: Maybe CalculatedPoints • In the second argument of ‘fromMaybe’, namely ‘lpoints’
In the expression: fromMaybe (Nothing, Nothing) lpoints In a pattern binding:
(xl, yl) = fromMaybe (Nothing, Nothing) lpoint
P.S I decided that parseInput was important for the context, so it turns out that calculatePoints is also necessary, so I included them
calculatePoints :: Interval -> Double -> Points -> Bool -> Bool -> [Maybe CalculatedPoints]
calculatePoints interval step points True True =
[ Just (linearApproximation interval step points),
Just (segmentApproximation interval step points)
]
calculatePoints interval step points True False = [Just (linearApproximation interval step points), Nothing]
calculatePoints interval step points False True = [Nothing, Just (segmentApproximation interval step points)]
calculatePoints _ _ _ False False = [Nothing, Nothing]
parseInput :: IO [Maybe CalculatedPoints]
parseInput = do
input <- cmdArgs inputOptions
points <- case file input of
"" -> getPointsNoFile []
path -> getPointsFile path
return $ calculatePoints (left input, right input) 0.95 points (lm input) (sm input)
CodePudding user response:
Notice that fromMaybe
needs a default value of the same type. Below, your code commented with the mistake
main = do
resultPoints <- parseInput -- This has type [Maybe CalculatedPoints]
case resultPoints of
-- This is the case where input is a list with two Nothing's . Looks good :)
[Nothing, Nothing] -> putStrLn "Calculation failed. Perhaps you did not specify a method."
-- This case is missleading. First, You can match directly (Just calcpoints)
-- because the case where lpoints is Nothing, has being match before.
-- so there is no need to have an irrefutable pattern (i.e. a variable ignoring the shape)
-- Nevertheless, the error is below, not here
[lpoints, Nothing] -> do
putStrLn "Linear Aproxiation"
-- |- This has type a -> Maybe a -> a (sumary: you provide a default value for Nothing, otherwise extract whatever is within Just)
-- | |- The default value has type "(Maybe a, Maybe a)" => a tuple of maybes
-- | | |- This has value (Maybe CalculatedPoints)
let (xl, yl) = fromMaybe (Nothing, Nothing) lpoints -- THIS
-- |- Also this has type tuple of maybes. Therefore GHC is complaining
-- "you want me to extract a tuple but the value you provide is Maybe CalculatedPoints
-- How in the heck I get a tuple from that??"
prettyPoints xl yl
print $ xl
.
.
.
Now, If you want to type check your code, It should be something like below. Notice that It isn't a very good / idiomatic haskell code.
main = do
resultPoints <- parseInput
case resultPoints of
[Nothing, Nothing] -> putStrLn "Calculation failed. Perhaps you did not specify a method."
[lpoints, Nothing] -> do
putStrLn "Linear Aproxiation"
-- |- Provide a default value of the same type as the lpoints has "inside" the Just
let points = fromMaybe (Linear [] []) lpoints
-- |- not sure about this... But you can work it out
prettyPoints points??
print $ xl
Now, If you want more idiomatic code I'd suggest
main = do
resultPoints <- parseInput
case resultPoints of
[Nothing, Nothing] -> putStrLn "Calculation failed. Perhaps you did not specify a method."
[Just (Linear xl yl), Nothing] -> do
putStrLn "Linear Aproxiation"
prettyPoints xl yl
print $ xl
.
.
.
CodePudding user response:
I think I'd just delete most of this code. Here's a much simpler main
with the same behavior:
main = do
input <- cmdArgs inputOptions
points <- case file input of
"" -> getPointsNoFile []
path -> getPointsFile path
let interval = (left input, right input)
unless (lm input || sm input) (putStrLn "Calculation failed. Perhaps you did not specify a method.")
when (lm input) $ do
putStrLn "Linear Aproxiation" -- sic
print (linearApproximation interval 0.95 points)
when (sm input) $ do
putStrLn "Segment Aproxiation"
print (segmentApproximation interval 0.95 points)
No Maybe
needed; no CalculatedPoints
needed (...probably. unless linearApproximation
and segmentApproximation
are weirder than their names sound); no fragile guaranteed-length-two list needed; and less code repetition between cases. There is still a little bit of repetition between the linear and segment printing code; if you really want, you could abstract those a little bit.
data ApproximationMethod = AM
{ name :: String
, approx :: Interval -> Double -> Points -> Points
, active :: InputOptions -> Bool
}
allMethods :: [ApproximationMethod]
allMethods = [AM "Linear" linearApproximation lm, AM "Segment" segmentApproximation sm]
main = do
{- ... -}
for_ approximationMethods $ \am -> when (active am input) $ do
putStrLn $ name am " Aproxiation"
print (approx am interval 0.95 points)
But for this little repeated code, that seems like overkill.