繁体   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