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

lil*_*zek 1 haskell type-inference

我是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))
Run Code Online (Sandbox Code Playgroud)

在没有明确类型的情况下表达:

(Monomio (Numero (Integer 15)) (Integer 20))
Run Code Online (Sandbox Code Playgroud)

这个表达式:

main = print (Monomio (Integer 15) (Integer 20))
Run Code Online (Sandbox Code Playgroud)

更短的是不明确的,因为(整数15)不能适合(Incognita字符串)的定义,但它不编译:

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))'
Run Code Online (Sandbox Code Playgroud)

为什么?

eps*_*lbe 5

Numero表达式中的

(Monomio (Numero (Integer 15)) (Integer 20))
Run Code Online (Sandbox Code Playgroud)

是不是一个类型-但一个类型值构造,所以你需要它,以构建一些类型的值Elemento.

一种方法是使用fromIntegral以实现"自动"转换.

对于String-like你有OverloadedStrings-Language扩展,但是对于数字类型,没有类似的东西(至少据我所知).

旁注:我认为它使您的代码更加混乱,因为您有一种类型Numero和类型构造函数,Numero后者构造类型的东西Elemento.

我会用NumElementoVarElemento什么等.


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

data Polynomial1 = P1 String [Rational]
newtype Polynomial  = P [Polynomial1]
Run Code Online (Sandbox Code Playgroud)

这里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- 虽然显然是真的,你碰巧在无限的比较过程中运行).

  • 在该表达式中,`Numero`不是类型构造函数,它是一个值构造函数.类型构造函数构造,井,类型,例如`Maybe`,`[]`,`Either`,`(,)`等.值构造函数改为构造值,例如`Just`,`(:)`,`Left`, `(,)`等.其中一些碰巧具有相同的名称,但存在于不同的名称空间中. (2认同)