如何使用"newtype"参数定义Haskell函数?

dma*_*man 4 haskell types newtype

我已经定义了一个名为Poly的新类型.Poly是多项式的列表表示(Num的列表),我正在尝试定义一个函数"chop",它从Poly的末尾取消多余的0.

Chop将一个Poly作为参数,然后返回Poly.出于某种原因,我收到以下错误消息:

期望一个约束,但'Poly a'在'chop'的类型签名中有'*'类型:chop :: Poly a => a - > a

newtype Poly a = P [a]

chop :: Poly a => a -> a
chop l = if (last l) == 0 then chop (init l) else l
Run Code Online (Sandbox Code Playgroud)

Mok*_*sha 10

在Haskell中,=>类型签名中的字符表示类型限制.这与Haskell类型类一起使用,以抽象出可以在高级抽象级别使用的函数的实现细节.

在您的示例中,Poly a根据类型系统是一个全新的类型,而不是类型类,因此您的函数chop可能是直接对它进行操作:

chop :: Poly a -> Poly a
chop (P l) = if (last l) == 0 then chop (P $ init l) else P l
Run Code Online (Sandbox Code Playgroud)

但是等等,这不编译!限制来自与0的比较:(last l) == 0.在这里我们隐含地说我们希望我们的元素Poly a可以与零相比,或者换句话说a必须是一个实例Num a.毕竟,你无法砍掉多项式Poly (Maybe String).我们修改的类型签名是:

chop :: Num a => Poly a -> Poly a
chop (P l) = if (last l) == 0 then chop (P $ init l) else P l
Run Code Online (Sandbox Code Playgroud)

需要考虑的一件事是:因为你使用的是a newtype而不是普通的旧版本type,Haskell将你Poly a视为一种全新的类型.为了使其可与列表互换,您可以使用类型同义词:

type Poly a = [a]
Run Code Online (Sandbox Code Playgroud)

这将简化chop的实现:

chop :: Num a => Poly a -> Poly a
chop l = if (last l) == 0 then chop (init l) else l
Run Code Online (Sandbox Code Playgroud)