Haskell中不同类型的乘法

Max*_*xym 10 haskell types

我是哈斯凯尔的新手,我不时遇到一个问题,我将用几句话来描述.想象一下,我想为不同的度量声明不同的类型,因此Haskell类型系统会在我的公式中找到错误:

newtype Dist = Km Float
newtype Time = H Float
newtype Velocity = KmH Float

(/) :: Dist ? Time ? Velocity
(Km d) / (H t) = KmH (d / v)

(*) :: Velocity ? Time ? Dist
(KmH v) * (H t) = Km (v * t)
Run Code Online (Sandbox Code Playgroud)

所以,每当我尝试在我的公式中使用错误的度量单位时,编译器就会咬人.

问题是我不能像这样实现ad-hoc polimorphism.使用此代码,我带来了歧义 - 编译器可以区分我的运算符*和Prelude中定义的运算符.由于我需要不同类型的参数,因此也无法声明Num类的实例.

我想知道人们通常如何解决这个问题.

提前致谢!

aug*_*tss 6

如果你愿意,你可以隐藏通常的(*)

import Prelude hiding((*))
Run Code Online (Sandbox Code Playgroud)

或隐藏所有的Nu​​m

import Prelude hiding(Num(..))
Run Code Online (Sandbox Code Playgroud)

然后你可以定义你自己的乘法,可能是沿着这条线

class Mul a b c | a b -> c, b c -> a, c a -> b where
    (*) :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)


fuz*_*fuz 5

您可以尝试重新配置您的单位系统.尝试这样的事情:

data Unit = Unit String
          | Unit :/: Unit
          | Unit :*: Unit
          | Unit :^: Int
          deriving (Show,Eq)

instance Num Unit where
  -- Insert reasonable definition here
  x * y = ...

data UnitNum n = UN n Unit

instance Num (Num n) => UnitNum n where
  UN n u + Un k u' | u == u' = UN (n+k) u
                   | otherwise = error ...
  -- insert other definitions here.

km,h,kmh :: Unit

km = Unit "km"
h = Unit "h"
kmh = km / h
Run Code Online (Sandbox Code Playgroud)

编辑:

类似的东西,但在维度包中实现了完全不同.阅读源代码,它是有文化的Haskell,非常好理解.对于大多数科学应用,此代码应该足够好.

  • 请注意,此实现纯粹是动态的.有趣的部分是让工作人员完成工作(就像尺寸一样)! (4认同)