I am working on this program for better understanding of haskell and state monad. I made a module Rectangle which has data type Rectangle and a function to increment the length of the rectangle. To increment the length i made a function plus. Could there have been a better way than this plus function? Also while incrementing i am doing addition with a new rectangle which is logically incorrect. How to perform the increment in the correct way? Is there any way in which instead of giving the default width the compiler prompts the user for width? How can i sort of extract one or more rectangle or any attribute(length or breadth) while doing stateful computation?
{-# LANGUAGE TemplateHaskell, TypeOperators #-}
module Rectangle(Rectangle(Rectangle),GlobState(GlobState),plus,newGlobState,r1,r2,r3,incr) where
import Control.Monad.State hiding (modify)
import Data.Label (mkLabels)
import Data.Label.Pure ((:->))
import Data.Label.PureM
type Length = Int
type Width = Int
data Rectangle = Rectangle Length Width deriving (Eq,Read,Show)
data GlobState = GlobState { _r1 :: Rectangle , _r2 :: Rectangle , _r3 :: Rectangle } deriving Show
$(mkLabels [''GlobState])
plus :: Rectangle -> Rectangle -> Rectangle
plus (Rectangle x z) (Rectangle y w) = Rectangle (x+y) z
newGlobState:: GlobState
newGlobState = GlobState { _r1 = Rectangle 0 10, _r2 = Rectangle 0 10, _r3 = Rectangle 0 10}
incr :: (GlobState :-> Rectangle) -> State GlobState ()
incr x = modify x (plus (Rectangle 1 10))
I have made a new module for selecting one of the rectangles:
{-# LANGUAGE TemplateHaskell, TypeOperators #-}
module ChooseRect(ChooseRect(ChooseRect),makeChoice,select) where
import Rectangle
import Control.Monad.State hiding (modify)
import Data.Label (mkLabels)
import Data.Label.Pure ((:->))
import Data.Label.PureM
type Choice = Int
data ChooseRect = ChooseRect Rectangle Rectangle deriving Show
makeChoice:: Rectangle-> Rectangle->ChooseRect
makeChoice p1 p2 = ChooseRect p1 p2
select:: ChooseRect -> Choice -> Rectangle
select (ChooseRect (Rectangle x z) (Rectangle y w)) choice = if (choice==1)
then let selectedRectangle = Rectangle x z
in selectedRectangle
else let selectedRectangle = Rectangle y w
in selectedRectangle
But when i made changes to main module i m getting error.
module Main where
import Rectangle
import ChooseRect
import Control.Monad.State hiding (modify)
import Data.Label (mkLabels)
import Data.Label.Pure ((:->))
import Data.Label.PureM
main :: IO ()
main = do
let x = flip execState newGlobState $ do
incr r1
incr r2
incr r1
incr r3
incr r3
let y=makeChoice r1 r2
print y
print x
The error message is
Couldn't match expected type `Rectangle'
with actual type `Data.Label.Abstract.Lens
(~>0) GlobState Rectangle'
In the first argument of `makeChoice', namely `r1'
In the expression: makeChoice r1 r2
In an equation for `y': y = makeChoice r1 r2
Please explain the error and how to remove it
incrforces the width of the rectangle to be 10? (All your rectangles have width 10 for now, but if e.g.r3started asRectangle 0 5, would you really wantincrto make itRectangle 1 10?)pluslogically incorrect, it hides a bug as well.incrforces the width of the rectangle to be 10.