繁体   English   中英

如何在 Haskell 中的自定义数据类型上使用预定义的 function(例如 ==、tail)?

[英]How to use predefined function (e.g. ==, tail) on my custom data type in Haskell?

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

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 )或在上述错误情况下将整数列表与我的自定义数据类型进行比较的问题? 我的猜测是我必须自己定义操作,但我不知道该怎么做。

当您为 class 编写实例时,例如

class C a where
  method :: a -> a

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

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

因此,您不能将Vector类型的 arguments 与模式[]匹配,也不能在其上使用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)时, ==运算符应该可以正常工作。

您可以概括您的类型 class 以采用两个类型变量来适应 integer 乘法和向量点积的两种不同操作。 但是,这需要两个特定于 GHC 的扩展,从而排除了您对 Hugs 的使用。

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}

-- a -> b means that the second type is uniquely determined by the
-- first. Without it, you would need explicitly type an expression
-- involving factor.
class VEC a b | a -> b  where
    factor :: a -> a -> b

instance VEC Int Int where
    -- a ~ Int, b ~ Int
    factor x y = x * y

-- newtype instead of data, for efficiency if nothing else
newtype Vector = VECTOR [Int] deriving (Show, Eq)

instance VEC Vector Int where
    -- a ~ Vector, b ~ Int
    factor (VECTOR xs) (VECTOR ys) = sum $ zipWith (*) xs ys


main = do
  print $ factor (3 :: Int) 3
  print $ factor (VECTOR [1,2,3]) (VECTOR [4,5,6])

如果没有功能依赖,您将不得不编写

main = do
    print (factor (3 :: Int) 3 :: Int)
    print (factor (VECTOR [1,2,3]) (VECTOR [4,5,6]) :: Int)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM