必须存在一种良好的惯用方式来表达类型级别的Haskell中的一般计算。我能想到的就是这种(非法的)OO模仿。
class Computation where
compute :: Computation -> Double -> Double
data Id = Id
instance Computation Id where
compute _ = id
data Square a = Computation a => Square a
instance Computation (Square a) where
compute (Square underlying) x = sqr $ compute underlying x where square x = x*x
data Scale a = Computation a => Scale a Double
compute (Scale underlying c) x = c * compute underlying x
理想情况下,我希望保持开放性,因此this方法对我没有吸引力。我要求的太多了吗?
答案 0 :(得分:3)
你当然可以使用你拥有的方法来做到这一点,你只需要正确地获取语法和一些细节,但这当然有效:
class Computation a where
compute :: a -> Double
instance Computation Double where
compute = id
data Square a = Square a
instance Computation a => Computation (Square a) where
compute (Square underlying) = square $ compute underlying where square i = i * i
data Scale a = Scale a Double
instance Computation a => Computation (Scale a) where
compute (Scale underlying c) = c * compute underlying
data Add a = Add a Double
instance Computation a => Computation (Add a) where
compute (Add underlying c) = c + compute underlying
test :: Add (Scale (Scale (Square Double)))
test = Add (Scale (Scale (Square 2) 5) 0.5) 100
main :: IO ()
main = print $ compute test
请注意,我必须为Computation
添加Double
的实例,这只是const
。 test
表达式应该等同于(((2^2) * 5) * 0.5) + 100
,实际上比较这两个结果我会得到相同的值。
答案 1 :(得分:0)
这取决于你想用计算做什么,但一个惯用的方法是:
data Computation = Computation { compute :: Double -> Double }
然后你可以:
idCmp :: Computation
idCmp = Computation id
squareCmp :: Computation
squareCmp = Computation (\i -> i * i)
composeCmp :: Computation -> Computation -> Computation
composeCmp b a = Computation (compute b . compute a)
scaleCmp :: Double -> Computation
scaleCmp r = Computation (r*)
等。你可以称之为“计算组合器”。