在尝试调试我的程序中的问题时(使用Gloss将2个具有相同半径的圆圈绘制成不同的大小),我偶然发现了一个奇怪的情况.在我处理对象的文件中,我有以下定义*:
type Coord = (Float,Float)
data Obj = Player { oPos :: Coord, oDims :: Coord }
Run Code Online (Sandbox Code Playgroud)
在导入Objects.hs的主文件中,我有以下定义:
startPlayer :: Obj
startPlayer = Player (0,0) 10
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为我为玩家添加和更改字段,并且忘记更新Player之后(其尺寸由单个数字确定以表示半径,但我将其更改为a startPlayer来表示(宽度,高度);如果我做的话玩家对象是一个非圆圈).
令人惊奇的是,上面的代码编译并运行,尽管第二个字段是错误的类型.
我首先想到的可能是我打开了不同版本的文件,但对编译程序中的任何文件的任何更改都会反映出来.
接下来我认为可能Coord由于某种原因没有被使用.注释会startPlayer产生编译器错误,甚至更奇怪的是,更改startPlayerin 10会导致适当的响应(更改起始大小startPlayer); 再次,尽管它是错误的类型.为了确保它正确读取数据定义,我在文件中插入了一个拼写错误,它给了我一个错误; 所以我正在查看正确的文件.
我试图粘贴2段以上的到自己的文件,并吐出预期误差的第二场Player中Player是不正确.
什么可能允许这种情况发生?您认为这是Haskell的类型检查器应该阻止的事情.
我应该注意到,我原来的问题的答案,即两个被认为是相同半径的圆被绘制成不同的大小,其中一个半径实际上是负的.
一般的问题是在为现有对象添加实例时哪个模块结构更方便?有哪些优点和缺点?
假设我想为Seq类型添加NFData实例.我可以把它放在:
Data.Sequence.Extra(在vty包中做同样的事情)Data.Sequence.Instances.NFData (更确切)Control.DeepSeq.InstancesControl.DeepSeq.Instances.Sequence当我既没有类型类也没有数据类型时就是这种情况.另一种常见的情况是,我拥有一个类型类型,并希望从Hackage的一些"重"包中添加数据类型的实例,比如OpenGL.假设我设计的类型类很轻,与OpenGL没有直接关系.我不希望我的类型类依赖于"重"包,所以我想将OpenGL实例放在一个单独的模块中(这是我的直觉,如果你有其他意见,我们来讨论它).那么,这个模块应该是什么:
MyClass.Instances.OpenGLGraphics.Rendering.OpenGL.Extra (连同其他课程的实例)Graphics.Rendering.OpenGL.Instances.MyClass什么是更灵活的解决方案?在某些时候,OpenGL可以替换为其他库,或者也可以替换MyClass.有微妙的细微差别吗?
此外,如果选择MyClass.Instances变体,哪个方案更好:
MyClass.Class类本身的模块和基本实例和MyClass模块重新导出它(也许MyClass.Instances)MyClass类和基本实例的模块,并重新MyClass.All导出所有内容MyClass 类和基本实例的模块,没有用于重新导出的模块.我正在使用以下类型类:
module T where
class T a where
v :: a
Run Code Online (Sandbox Code Playgroud)
T Int我实现的一个实例:
import T
import A (av)
instance T Int where
v = 0
main = putStrLn (av ++ show v)
Run Code Online (Sandbox Code Playgroud)
还有一个模块,我想使用一个值,也有一个实例T Int.
module A where
import T
instance T Int where
v = 0
av = "value from A"
Run Code Online (Sandbox Code Playgroud)
问题是这不起作用:
$ runghc Main.hs
Main.hs:4:9:
Duplicate instance declarations:
instance T Int -- Defined at Main.hs:4:9-13
instance T Int -- Defined at A.hs:3:9-13
Run Code Online (Sandbox Code Playgroud)
Haskell抱怨同一个实例有2个声明.我如何告诉他不要从中导入实例B,或统一这两个实例,或仅使用实例Main …
我尝试按照Quickcheck简介进行操作,并想测试我的函数,该函数包含包含数字的字符串.为此,我定义了一个Arbitrary实例Char:
instance Arbitrary Char where
arbitrary = choose ('0', '9')
Run Code Online (Sandbox Code Playgroud)
但是ghc抱怨说:
A.hs:16:10:
Duplicate instance declarations:
instance Arbitrary Char -- Defined at A.hs:16:10
instance [overlap ok] [safe] Arbitrary Char
-- Defined in ‘Test.QuickCheck.Arbitrary’
Run Code Online (Sandbox Code Playgroud)
我怎么能告诉它忘记已定义的实例并使用我自己的实例?或者它根本不会那样工作(这会很奇怪,因为教程采用了这种方法)?
haskell ×4
typeclass ×2
hierarchy ×1
instance ×1
module ×1
namespaces ×1
quickcheck ×1
types ×1