- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
下面似乎工作......但它似乎很笨拙。
data Point = Point Int Int
data Box = Box Int Int
data Path = Path [Point]
data Text = Text
data Color = Color Int Int Int
data WinPaintContext = WinPaintContext Graphics.Win32.HDC
class CanvasClass vc paint where
drawLine :: vc -> paint -> Point -> Point -> IO ()
drawRect :: vc -> paint -> Box -> IO ()
drawPath :: vc -> paint -> Path -> IO ()
class (CanvasClass vc paint) => TextBasicClass vc paint where
basicDrawText :: vc -> paint -> Point -> String -> IO ()
instance CanvasClass WinPaintContext WinPaint where
drawLine = undefined
drawRect = undefined
drawPath = undefined
instance TextBasicClass WinPaintContext WinPaint where
basicDrawText (WinPaintContext a) = winBasicDrawText a
op :: CanvasClass vc paint => vc -> Box -> IO ()
op canvas _ = do
basicDrawText canvas WinPaint (Point 30 30) "Hi"
open :: IO ()
open = do
makeWindow (Box 300 300) op
winBasicDrawText :: Graphics.Win32.HDC -> WinPaint -> Point -> String -> IO ()
winBasicDrawText hdc _ (Point x y) str = do
Graphics.Win32.setBkMode hdc Graphics.Win32.tRANSPARENT
Graphics.Win32.setTextColor hdc (Graphics.Win32.rgb 255 255 0)
Graphics.Win32.textOut hdc 20 20 str
return ()
windowsOnPaint :: (WinPaintContext -> Box -> IO ()) ->
Graphics.Win32.RECT ->
Graphics.Win32.HDC ->
IO ()
windowsOnPaint f rect hdc = f (WinPaintContext hdc) (Box 30 30)
makeWindow :: Box -> (WinPaintContext -> Box -> IO ()) -> IO ()
makeWindow (Box w h) onPaint =
Graphics.Win32.allocaPAINTSTRUCT $ \ lpps -> do
hwnd <- createWindow w h (wndProc lpps (windowsOnPaint onPaint))
messagePump hwnd
data Canvas = Canvas {
drawLine :: Point -> Point -> IO (),
drawRect :: Box -> IO (),
drawPath :: Path -> IO ()
}
hdc2Canvas :: Graphics.Win32.HDC -> Paint -> IO ( Canvas )
hdc2Canvas hdc paint = Canvas { drawLine = winDrawLine hdc paint ... }
data Paint = Paint {
setFg :: Color -> IO () ,
setBg :: Color -> IO ()
}
最佳答案
接口(interface)
首先,您需要问“我的要求是什么?”。让我们用简单的英语说明我们想要 Canvas 做什么(这些是我根据您的问题做出的猜测):
show
类说“某些类型可以表示为字符串”。 class ShapeCanvas c where -- c is the type of the Canvas
draw :: Shape -> c -> c
class TextCanvas c where
write :: Text -> c -> c
class PaintCanvas p c where -- p is the type of Paint
load :: p -> c -> c
c
仅使用一次,显示为
c -> c
.这表明我们可以通过替换
c -> c
来使这些更通用。与
c
.
class ShapeCanvas c where -- c is the type of the canvas
draw :: Shape -> c
class TextCanvas c where
write :: Text -> c
class PaintCanvas p c where -- p is the type of paint
load :: p -> c
PaintCanvas
看起来像
class
这在 Haskell 中是有问题的。类型系统很难弄清楚类中发生了什么,例如
class Implicitly a b where
convert :: b -> a
PaintCanvas
来缓解这种情况利用
TypeFamilies
延期。
class PaintCanvas c where
type Paint c :: * -- (Paint c) is the type of Paint for canvases of type c
load :: (Paint c) -> c
{-# LANGUAGE TypeFamilies #-}
module Data.Canvas (
Point(..),
Shape(..),
Text(..),
ShapeCanvas(..),
TextCanvas(..),
PaintCanvas(..)
) where
data Point = Point Int Int
data Shape = Dot Point
| Box Point Point
| Path [Point]
data Text = Text Point String
class ShapeCanvas c where -- c is the type of the Canvas
draw :: Shape -> c
class TextCanvas c where
write :: Text -> c
class PaintCanvas c where
type Paint c :: * -- (Paint c) is the type of Paint for canvases of type c
load :: (Paint c) -> c
c -> c
与
c
在 Canvas 类中。
op
.使用我们的新界面,它很简单:
op :: (TextCanvas c) => c
op = write $ Text (Point 30 30) "Hi"
ex :: (ShapeCanvas c) => c
ex = draw $ Path [Point 10 10, Point 20 20]
Path
为横冲程。我们需要某种方式将两个绘图步骤放在一起。有类型的东西
c -> c -> c
将会是完美的。我能想到的最简单的 Haskell 类是
Monoid a
的
mappend :: a -> a -> a
.一个
Monoid
需要身份和关联性。假设在 Canvas 上进行了绘图操作而使它们保持原状是否合理?这听起来很合理。假设三个绘图操作,以相同的顺序进行,即使前两个一起执行,然后第三个,或者如果第一个执行,然后第二个和第三个一起执行,也做同样的事情是否合理? ?同样,这对我来说似乎很合理。这建议我们可以写
ex
作为:
ex :: (Monoid c, ShapeCanvas c) => c
ex = (draw $ Path [Point 10 10, Point 20 20]) `mappend` (draw $ Path [Point 10 20, Point 20 10])
randomDrawing :: (MonadIO m, ShapeCanvas (m ()), TextCanvas (m ())) => m ()
randomDrawing = do
index <- liftIO . getStdRandom $ randomR (0,2)
choices !! index
where choices = [op, ex, return ()]
(Monad m) => Monoid (m ())
的实例。以便
ex
将工作。我们可以使用
Data.Semigroup.Monad
从 reducers 包中,或者自己添加一个,但这会使我们陷入不连贯的情况。将 ex 更改为:
ex :: (Monad m, ShapeCanvas (m ())) => m ()
ex = do
draw $ Path [Point 10 10, Point 20 20]
draw $ Path [Point 10 20, Point 20 10]
draw
中的单位。与第二个单位相同。我们这里的困难表明了额外的要求,我们一开始无法完全理解:
MonadIO
class 和 mtl 的 monad 类。
{-# LANGUAGE TypeFamilies #-}
module Data.Canvas (
Point(..),
Shape(..),
Text(..),
ShapeCanvas(..),
TextCanvas(..),
PaintCanvas(..)
) where
data Point = Point Int Int
data Shape = Dot Point
| Box Point Point
| Path [Point]
data Text = Text Point String
class Monad m => ShapeCanvas m where -- c is the type of the Canvas
draw :: Shape -> m ()
class Monad m => TextCanvas m where
write :: Text -> m ()
class Monad m => PaintCanvas m where
type Paint m :: * -- (Paint c) is the type of Paint for canvases of type c
load :: (Paint m) -> m ()
Monad
中的操作。米:
op :: (TextCanvas m) => m ()
op = write $ Text (Point 30 30) "Hi"
ex :: (ShapeCanvas m) => m ()
ex = do
draw $ Path [Point 10 10, Point 20 20]
draw $ Path [Point 10 20, Point 20 10]
randomDrawing :: (MonadIO m, ShapeCanvas m, TextCanvas m) => m ()
randomDrawing = do
index <- liftIO . getStdRandom $ randomR (0,2)
choices !! index
where choices = [op, ex, return ()]
checkerBoard :: (ShapeCanvas m, PaintCanvas m) => Paint m -> Paint m -> m ()
checkerBoard red black =
do
load red
draw $ Box (Point 10 10) (Point 20 20)
draw $ Box (Point 20 20) (Point 30 30)
load black
draw $ Box (Point 10 20) (Point 20 30)
draw $ Box (Point 20 10) (Point 30 20)
关于haskell - 存在反模式,如何避免,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19061828/
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!