簡體   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