实现增量功能

时间:2012-02-01 09:56:18

标签: haskell

我正在研究这个程序,以便更好地理解haskell和state monad。我创建了一个模块Rectangle,它具有数据类型Rectangle和一个增加矩形长度的函数。为了增加长度,我做了一个函数加。 是否有比这个加功能更好的方法?同时在增加时我正在添加一个逻辑上不正确的新矩形。 如何以正确的方式执行增量?有没有什么方法可以让编译器提示用户输出宽度,而不是给出默认宽度? 如何在进行有状态计算时提取一个或多个矩形或任何属性(长度或宽度)?

{-# 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))

我已经制作了一个用于选择其中一个矩形的新模块:

{-# 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

但是当我对主模块进行更改时,我遇到了错误。

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

错误消息是

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

请解释错误以及如何删除错误

1 个答案:

答案 0 :(得分:3)

  1. plus更好lengthenBy :: Length -> Rectangle -> Rectangle

    哦,你错误地使用了modify ...你需要使用来自Control.Monad.State modify 来自Data.Label.Pure的modify

    incr x = Control.Monad.State.modify $ Data.Label.Pure.modify x (lengthenBy 1)
    
  2. 查看函数getLine :: IO String(用于获取输入行)和read :: String -> Intreads :: String -> [(Int, String)](用于将其从String转换为{{1}前者更易于使用,但如果无法解析输入则崩溃)(以及putStr :: String -> IO ()putStrLn :: String -> IO ()来显示提示)。

    n.b。在Int中最外层的do-block中执行i / o,并将结果作为额外参数传递到您的 有状态计算。

  3. 替换

    main

    makeChoice r1 r2
    

    查看类型:

    makeChoice (get r1 x) (get r2 x)
    

    因此,r1, r2 :: GlobState :-> Rectangle makeChoice :: Rectangle -> Rectangle -> ChooseRect r1不适合传递给r2