首页 > 解决方案 > 如何在 Haskell 中对我的自定义数据类型使用预定义函数(例如 ==、tail)?

问题描述

我是haskell的新手,我在网上读到的任何东西都没有真正帮助我。我的任务是实现一个类型类VEC,它有一个函数factor,如果用户输入的不是两个数字而是两个向量类型的整数列表,它要么计算两个整数的乘法,要么执行两个矩阵的点积。我的代码如下所示:

data Vector = VECTOR [Int] deriving (Show, Eq)
class VEC a where
    factor :: a -> a -> a
instance VEC Int where
    factor a b = a*b
instance VEC Vector where
    factor xs [] = 0
    factor xs ys = (head xs) * (head ys) + factor (tail xs) (tail ys)

我假设 Vectors 是类型[Int],但现在我不太确定,因为在尝试使用 Hugs 编译代码时收到以下错误消息:

Hugs> :l kdp  
ERROR file:kdp.hs:7 - Type error in instance member binding  
*** Term           : []  
*** Type           : [a]  
*** Does not match : Vector

所以我的问题是:第一行实际上是什么意思?它是与作业一起给出的,我已经看到了许多类似的数据类型定义,但没有一个具有这种特定模式。然后如何解决无法使用预定义函数的问题,例如tail在上述错误情况下将整数列表与我的自定义数据类型进行比较?我的猜测是我必须自己定义操作,但我不知道该怎么做。

标签: functionhaskelltypeclass

解决方案


当您为类似的类编写实例时

class C a where
  method :: a -> a

您将所有参数外观 ( a) 替换为您正在为其编写实例的类型。例如在你的情况下:

{-# LANGUAGE InstanceSigs #-}
instance VEC Vector where
    factor :: Vector -> Vector -> Vector
    factor _ _ = undefined

因此,您不能将类型参数Vector与模式匹配,[]也不能在其上使用headtail函数,因为它们正在处理列表。但是,您Vector包含列表,因此您可以简单地解压缩它:

instance VEC Vector where
    factor _ (Vector []) = Vector [0] -- you need to return Vector as well
    factor (Vector xs) (Vector ys) =
      let Vector [x] = factor (Vector $ tail xs) (Vector $ tail ys)
      in Vector [(head xs) * (head ys) + x]

这是非常丑陋和局部的,你可以使用一些内置Data.List的机器让它更性感:

instance VEC Vector where
  factor (Vector xs) (Vector ys) =
    Vector [sum (zipWith (*) xs ys)]

当您使用deriving (Show, Eq)时,==操作员应该可以正常工作。


推荐阅读