约束中的模糊类型变量'blah'...如何修复?

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图形/