在尝试调试我的程序中的问题时(使用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的类型检查器应该阻止的事情.
我应该注意到,我原来的问题的答案,即两个被认为是相同半径的圆被绘制成不同的大小,其中一个半径实际上是负的.
有时,如果没有至少一种语言扩展,我想写的一段代码是不合法的.当试图在研究论文中实现这些想法时尤其如此,这些论文倾向于使用在撰写论文时可用的任何spiffy,超扩展版本的GHC,而没有明确实际需要哪些扩展.
结果是我经常在我的.hs文件的顶部找到这样的东西:
{-# LANGUAGE TypeFamilies
, MultiParamTypeClasses
, FunctionalDependencies
, FlexibleContexts
, FlexibleInstances
, UndecidableInstances
, OverlappingInstances #-}
Run Code Online (Sandbox Code Playgroud)
我不介意,但我常常觉得我正在做出盲目的牺牲来安抚GHC的大神.它抱怨如果没有语言扩展X,某段代码无效,所以我为X添加了一个pragma.然后它要求我启用Y,所以我为Y添加了一个pragma.到这个结束时,我已经启用我不太了解的三个或四个语言扩展,我不知道哪些是"安全的".
用"安全"来解释我的意思:
我明白这UndecidableInstances是安全的,因为虽然它可能导致编译器不终止,只要代码编译它就不会有意想不到的副作用.
另一方面,OverlappingInstances显然是不安全的,因为它使我很容易意外地编写产生运行时错误的代码.
所以我的问题是:
是否有GHCextensions列表被认为是"安全的"并且"不安全"?
如何显式导入类型类实例?另外,如何使用合格的导入进行此操作?
目前,我正在做
import Control.Monad.Error ()
Run Code Online (Sandbox Code Playgroud)
导入我可以用于的monad实例(Either String).以前,我用过
import Control.Monad.Error
Run Code Online (Sandbox Code Playgroud)
我对其中任何一个都不满意,因为Monad实例是隐式导入的.
有了这个代码
import Control.Monad
import Control.Applicative
import Control.Monad.State
class DefVal a where
defVal :: a
instance (DefVal a) => Alternative (Either a) where
empty = Left defVal
(Left _) <|> x = x
x <|> _ = x
instance (DefVal a) => MonadPlus (Either a) where
mzero = empty
mplus = (<|>)
newtype ErrString = ErrString { toString :: String }
deriving Show
instance DefVal ErrString where
defVal = ErrString "Default Error String"
Run Code Online (Sandbox Code Playgroud)
我收到错误消息:
Duplicate instance declarations:
instance DefVal a => …Run Code Online (Sandbox Code Playgroud)