相关疑难解决方法(0)

类型检查器允许非常错误的类型替换,程序仍然编译

在尝试调试我的程序中的问题时(使用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段以上的到自己的文件,并吐出预期误差的第二场PlayerPlayer是不正确.

什么可能允许这种情况发生?您认为这是Haskell的类型检查器应该阻止的事情.


我应该注意到,我原来的问题的答案,即两个被认为是相同半径的圆被绘制成不同的大小,其中一个半径实际上是负的.

haskell types

98
推荐指数
2
解决办法
3569
查看次数

如何使用实例组织Haskell模块:坚持数据类型与类型类?

一般的问题是在为现有对象添加实例时哪个模块结构更方便?有哪些优点和缺点?

假设我想为Seq类型添加NFData实例.我可以把它放在:

  • Data.Sequence.Extra(在vty包中做同样的事情)
  • Data.Sequence.Instances.NFData (更确切)
  • Control.DeepSeq.Instances
  • Control.DeepSeq.Instances.Sequence

当我既没有类型类也没有数据类型时就是这种情况.另一种常见的情况是,我拥有一个类型类型,并希望从Hackage的一些"重"包中添加数据类型的实例,比如OpenGL.假设我设计的类型类很轻,与OpenGL没有直接关系.我不希望我的类型类依赖于"重"包,所以我想将OpenGL实例放在一个单独的模块中(这是我的直觉,如果你有其他意见,我们来讨论它).那么,这个模块应该是什么:

  • MyClass.Instances.OpenGL
  • Graphics.Rendering.OpenGL.Extra (连同其他课程的实例)
  • Graphics.Rendering.OpenGL.Instances.MyClass

什么是更灵活的解决方案?在某些时候,OpenGL可以替换为其他库,或者也可以替换MyClass.有微妙的细微差别吗?

此外,如果选择MyClass.Instances变体,哪个方案更好:

  • MyClass.Class类本身的模块和基本实例和MyClass模块重新导出它(也许MyClass.Instances)
  • MyClass类和基本实例的模块,并重新MyClass.All导出所有内容
  • MyClass 类和基本实例的模块,没有用于重新导出的模块.

haskell module instance hierarchy typeclass

13
推荐指数
1
解决办法
1473
查看次数

如何告诉Haskell不从两个模块导入相同的实例?

我正在使用以下类型类:

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 …

haskell namespaces typeclass name-conflict

7
推荐指数
1
解决办法
246
查看次数

因为它已经存在,所以无法为`Char`定义自定义`Arbitrary`实例

我尝试按照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 quickcheck

6
推荐指数
1
解决办法
380
查看次数