Haskell - 在构造函数中推断类型

Haskell - Infer the type in constructor

我是 Haskell 世界的新手,所以这可能是一个基本问题。

这个代码可以吗:

data Numero =
  Integer Integer |
  Rational Rational |
  Double Double
  deriving (Show)
data Elemento =
  Numero Numero |
  Incognita String
  deriving (Show)

data Monomio = Monomio {base :: Elemento, exp :: Numero} deriving(Show)

main = print (Monomio (Numero (Integer 15)) (Integer 20))

在没有显式类型的情况下表达:

(Monomio (Numero (Integer 15)) (Integer 20))

?

这个表达式:

main = print (Monomio (Integer 15) (Integer 20))

哪个更短没有歧义,因为 (Integer 15) 不符合 (Incognita String) 的定义,但它不编译:

main.hs:13:24:
    Couldn't match expected type `Elemento' with actual type `Numero'
    In the first argument of `Monomio', namely `(Integer 15)'
    In the first argument of `print', namely
      `(Monomio (Integer 15) (Integer 20))'

为什么?

表达式中的Numero

(Monomio (Numero (Integer 15)) (Integer 20))

不是类型 - 而是 type 值构造函数,因此您需要它才能构造 something 类型的值 Elemento.

一种方法是使用 fromIntegral 以实现 "automatic" 转换。

对于 String-like 你有 OverloadedStrings-Language extension 但对于数字类型没有这样的东西(至少据我所知)。

附带说明:我认为这会让您的代码更加混乱,因为您有一个 Numero 类型和一个 Numero 类型构造函数,后者构造了 Numero 类型的东西=13=].

我会使用 NumElementoVarElemento 或类似的东西。


一种更简洁但完全不同的方法(如我的评论中所写)是使用多项式而不是单体。

data Polynomial1 = P1 String [Rational]
newtype Polynomial  = P [Polynomial1]

这里P1 "X" [1,2,3]代表p(x) = 1 + 2*x + 3*x²P [P1 "X" [1,2], P1 "Y" [0,1]]代表p(x,y) = 1 + 2*x + y

这种方法解决了许多发生的问题,如果你小心,你甚至可以表示泰勒级数(除了你不检查你是否不检查 cosine == cosine - 虽然显然是正确的,但你碰巧 运行在无限比较过程中)。