簡體   English   中英

Haskell類型類型約束和演繹

[英]Haskell Typeclass Type Constraints and Deduction

我一直在閱讀“Learn You a Haskell”一書,我正試圖將我的腦袋包裹在Haskell Type Classes中。 作為練習,我正在嘗試創建一個簡單的矢量類型類。 以下代碼片段給了我一些悲傷(導致我第一篇發布到StackOverflow):

data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)

class Vector a where
    (<*) :: (Num b) => a -> b -> a

instance (Num a) => Vector (Vec2 a) where
    Vec2 (x,y) <* a = Vec2 (a*x, a*y)

我收到以下錯誤消息:

Could not deduce (a~b) from the context (Num a) or from (Num b) bound by the type signature for
    <* :: Num b => Vec2 a -> b -> Vec2 a

這似乎是Num在類型類應該提供的類型指定a ,和Num a實例中應該提供的類型spefication xy ,那么為什么抱怨? 我對這段代碼有什么誤解?

(*) :: Num a => a -> a -> a 但是,當您實際嘗試使用* ,實際上您將兩個具有Num實例的不相關類型相乘,並且編譯器無法推斷它們是相同的。

為了更清楚地解釋它,請看<*的類型和b的通用量化

(<*) :: (Num b) => a -> b -> a

你在這里說的是,給我任何類型的Num實例,我將能夠將它與我的向量相乘,但你想說的是不同的東西。

你需要知道a類型Vec2 a中的b與類型(<*) :: Num b => a -> b -> a ,然后才能將它們相乘。 這是一個使用typefamilies來確保這種約束的解決方案。

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}

data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)

class (Num (VectorOf a)) => Vector a where
    type VectorOf a :: *
    (<*) :: a -> (VectorOf a) -> a

instance (Num a) => Vector (Vec2 a) where
    type VectorOf (Vec2 a) = a
    Vec2 (x,y) <* a = Vec2 (a*x, a*y)

編譯器無法驗證所涉及的兩個Num實例實際上是否為同一類型。 當然,它們都是Num實例,但是還需要它們必須是同一個實例。

否則,你可以寫這樣的東西:

Vec2 (1 :: Double, 2 :: Double) <* (3 :: Int)

什么時候不能飛,ex: (1 :: Double) * (3 :: Int)

我認為問題是(*)的類型(Num a) => a -> a -> a而不是(Num a, Num b) => a -> b -> a complier expect。

我不熟悉Haskell的數字轉換,但我的解決方法有限,因為第二個參數是Integral一個實例。

data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)    

class Vector a where
    (<*) :: (Integral b) => a -> b -> a

instance (Num a) => Vector (Vec2 a) where
    Vec2 (x,y) <* a = Vec2 (x*b, y*b)
        where b = fromIntegral a

因為fromIntegral有類型(Integral a, Num b) => a -> b ,它可以根據需要轉換*的第二個參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM