stu*_*ith 6 haskell type-variables
我正在尝试在Haskell中编写一个简单的光线跟踪器.我想定义一个类型类,表示可用的各种表面,并有一个函数来确定光线与它们相交的位置:
{-# LANGUAGE RankNTypes #-}
data Vector = Vector Double Double Double
data Ray = Ray Vector Vector
class Surface s where
intersections :: s -> Ray -> [Vector]
-- Obviously there would be some concrete surface implementations here...
data Renderable = Renderable
{ surface :: (Surface s) => s
, otherStuff :: Int
}
getRenderableIntersections :: Renderable -> Ray -> [Vector]
getRenderableIntersections re ra = intersections (surface re) ra
Run Code Online (Sandbox Code Playgroud)
但是这给了我错误:
Ambiguous type variable 's' in the constraint:
'Surface'
arising from a use of 'surface'
Run Code Online (Sandbox Code Playgroud)
(实际代码更复杂,但我试图将其提炼为更简单的东西,同时保持我想要实现的目标).
我该如何解决?或者,鉴于我来自标准的OO背景,我从根本上做错了什么?
scl*_*clv 10
请不要使用存在类型!你可以,但没有意义.
从功能的角度来看,您可以完全放弃Surface的类型类概念.A Surface是将Ray映射到Vector列表的东西,不是吗?所以:
type Surface = Ray -> [Vector]
data Renderable = Renderable
{ surface :: Surface
, otherStuff :: Int
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你真的想要,你可以拥有一个ToSurface基本上与你给出的类型类:
class ToSurface a where
toSurface :: a -> Surface
Run Code Online (Sandbox Code Playgroud)
但这仅仅是为了方便和特殊的多态性.您的模型中没有任何内容需要它.
一般来说,存在的用例非常少,但至少有90%的时间可以用存在的方式替换它所代表的功能,并获得更清晰,更容易推理的东西.
此外,即使你可能有太多的东西要接受,而问题也不完全匹配,你可能会发现Conal在指称性设计上的一些有用的内容:http://conal.net/blog/posts/想法上语义换3D图形/