我正在研究这个程序,以便更好地理解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
请解释错误以及如何删除错误
答案 0 :(得分:3)
比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)
查看函数getLine :: IO String
(用于获取输入行)和read :: String -> Int
或reads :: String -> [(Int, String)]
(用于将其从String
转换为{{1}前者更易于使用,但如果无法解析输入则崩溃)(以及putStr :: String -> IO ()
或putStrLn :: String -> IO ()
来显示提示)。
n.b。在Int
中最外层的do-block中执行i / o,并将结果作为额外参数传递到您的
有状态计算。
替换
main
与
makeChoice r1 r2
查看类型:
makeChoice (get r1 x) (get r2 x)
因此,r1, r2 :: GlobState :-> Rectangle
makeChoice :: Rectangle -> Rectangle -> ChooseRect
和r1
不适合传递给r2
。