The following asks for 2 sets of data (with corresponding x and y values), calculates a linear equation that matches the data as closely as possible, then allows you to play around with the equation by substituting x values. import Data.Charslope :: [Float] -> [Float] -> Floatslope xs ys    | xN /= yN = error $ x len:  ++ show xN ++  y len:  ++ show yN    | otherwise = (xN * (sum $ coorProds xs ys) - xSum * ySum) /        (xN * (sum $ squares xs) - (xSum * xSum))    where        (xN,yN) = (fromIntegral $ length xs, fromIntegral $ length ys)        (xSum,ySum) = (sum xs, sum ys)intercept :: [Float] -> [Float] -> Floatintercept xs ys    | xN /= yN = error $ x len:  ++ show xN ++  y len:  ++ show yN    | otherwise = (ySum - (b * xSum)) / xN    where        b = slope xs ys        (xN,yN) = (fromIntegral $ length xs, fromIntegral $ length ys)        (xSum,ySum) = (sum xs, sum ys)getEquation :: [Float] -> [Float] -> ((Float -> Float),Float,Float)getEquation xs ys = (\x -> (inter + (b * x)) , inter, b)    where        inter = intercept xs ys        b = slope xs yscoorProds :: [Float] -> [Float] -> [Float]coorProds xs ys = map (\(x,y) -> x * y) $ zip xs yssquares :: [Float] -> [Float]squares = map (\x -> x * x)cutIntoPair :: String -> (String,String)cutIntoPair = (\(x,y)-> (x,drop 1 y)) . break (== ' ')isFloat :: String -> BoolisFloat = all (\c -> isDigit c || c == '.')toFloat :: String -> FloattoFloat s    | isFloat s = read s :: Float    | otherwise = error $ show s ++  is not a numbergetPairs :: IO ([Float],[Float])getPairs = do    i <- getLine    let (x,y) = cutIntoPair i    if isFloat x        then do            (xs,ys) <- getPairs            return ((toFloat x : xs), (toFloat y : ys))        else return ([],[])useEquation :: (Float -> Float) -> IO ()useEquation e = do    putStr When x = ; x <- getLine    putStrLn $ y =  ++ (show $ e (toFloat x)) ++ \n    useEquation eshowEquation :: Float -> Float -> StringshowEquation i b = y =  ++ show i ++  +  ++ show b ++ xmain = do    putStrLn $ Enter x and y values seperated by a space\n\t ++        Then type a non-number to continue    (xs,ys) <- getPairs    let (linEq,i,b) = getEquation xs ys    putStrLn $ showEquation i b    putStrLn Enter x values to get their calculated y values    useEquation linEqI'm looking for general feedback, and suggestions regarding the following points:getEquation has a couple issues.I was able to write it point-free when the function only returned the equation, but now that I'm wrapping everything in a tuple, so I can also return the calculated slope and intercept values (to show the equation later), it's not behaving as I expected. I tried writing it as a section,  like (inter + (b *), but that attempts to apply + to the function (b*), which obviously results in a No instance error. My solution was to just wrap it in a lambda, but that's quite ugly, in my opinion.Is there a better way of dealing with the need to have the slope and intercept after the function is constructed than passing them back with the equation? The optimal solution would the ability to extract them out of the function, but I'm pretty sure that's not possible.cutIntoPair looks ugly too. It splits a string at the first space, then returns the 2 parts. Break leaves the space in the second slot though, so to remove it, I resorted to passing the result to a lambda that leaves the first part of the tuple the same, but drops the first char of the second slot. I'd like to know if there is a cleaner way to go about this task.The slope and intercept functions are slightly messy, but I had to cram a lot of math into the space. Tips on how to format it neater would be appreciated.To use it, type x and y values separated by a space, pressing enter between sets. When you're done entering, type a non-number, like so:2 44 812 24k
Calculate and use a linear equation based on sets of x and y values
haskell