gpt4 book ai didi

haskell - 对于简单的代码,类型约束变得巨大且不可读

转载 作者:行者123 更新时间:2023-12-04 23:19:52 24 4
gpt4 key购买 nike

请注意以下代码:

-- A n-dimensional axis aligned bounding box.
data AABB v a = AABB {
aabbMin :: !(v a),
aabbMax :: !(v a)
} deriving (Show)

-- `v` is a container, representing the number of dimensions. Ex:
-- type Box2DFloat = AABB V2 Float
-- type Box4DFloat = AABB V4 Float

-- A n-dimensional ray.
data Ray v a = Ray {
rayPos :: !(v a),
rayDir :: !(v a)
} deriving (Show)

-- Traces a n-d ray through a n-d box, returns
-- the intersection indexes (tmin, tmax).
intersectAABB
:: (Foldable f,
Metric f,
Ord a,
Num (f a),
Fractional (f a),
Floating a)
=> Ray f a
-> AABB f a
-> [a]
intersectAABB (Ray rayPos rayDir) (AABB aabbMin aabbMax)
= [tmin, tmax] where
t1 = (aabbMin - rayPos) / rayDir
t2 = (aabbMax - rayPos) / rayDir
tmin = foldr1 max $ liftI2 min t1 t2
tmax = foldr1 min $ liftI2 max t1 t2

这是一个普通的 Ray→AABB 交叉函数,除了 之外,它非常简单干净。类型签名,几乎比函数本身大 !有人建议我可以使用“封装我的需求”的种类约束来使其不那么冗长,但我找不到适本地“封装我的需求”的种类约束。在这种情况下,“我的需求”基本上是“类型的行为就像一个数字应该”。所以,在我看来,以下是有意义的:
class Real a where
... anything I want a real number to do ...

instance Real Float where
...

instance (Real a) => Real (V2 a) where
...

instance (Real a) => Real (V3 a) where
...

type AABB a = V2 a
type Ray a = V2 a

type Box2DFloat = AABB (V2 Float)
type Box4DFloat = AABB (V4 Float)
type Ray2D a = Ray (V2 a)
type Ray3DRatio = Ray (V3 Ratio)
... etc ...

这样,我的签名就会变成:
intersectAABB :: (Real r, Real s) => Ray r -> AABB r -> [s]

哪个看起来好多了。但是,如果没有人使用 Haskell 来定义这样的类,那应该是有原因的。没有“真实”类的原因是什么,如果定义这样的类是一个坏主意,那么我的问题的正确解决方案是什么?

最佳答案

使用约束同义词:

{-# LANGUAGE ConstraintKinds #-}

type ConstraintSynonym f a = (
Foldable f,
Metric f,
Ord a,
Num (f a),
Fractional (f a),
Floating a)

ConstraintKinds ,提升元组可用于表示约束的合取(而 () 可以指平凡满足的约束)。您现在可以使用 ConstraintSynonym而不是注释中的大约束元组。

关于haskell - 对于简单的代码,类型约束变得巨大且不可读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30289310/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com