gpt4 book ai didi

haskell - 跨类型类的模式匹配

转载 作者:行者123 更新时间:2023-12-02 21:44:52 24 4
gpt4 key购买 nike

我是 Haskell 新手,所以我很可能错过了一些明显的东西......

我正在尝试使用临时多态性编写通用颜色量化算法。然而,我在通过模式匹配获取数据时遇到了一些麻烦(我实际上还没有达到量化位)。

我无法简洁地描述这一点,所以这是我的代码的简化版本,它显示了问题:

{-# LANGUAGE FlexibleInstances #-}

import Data.Word

type ColourGrey = Word8

data ColourRGB = ColourRGB Word8 Word8 Word8
deriving (Show)

data ColourStream = Greys [ColourGrey]
| Colours [ColourRGB]
deriving (Show)

class Colour a where
extractStreamData :: ColourStream -> [a]

instance Colour ColourGrey where
extractStreamData (Greys x) = x

instance Colour ColourRGB where
extractStreamData (Colours x) = x

someColours = Colours [ColourRGB 255 0 0, ColourRGB 0 255 0, ColourRGB 0 0 255]
someGreys = Greys [0, 127, 255]

main :: IO ()
main = do
print $ extractStreamData someColours
print $ extractStreamData someGreys

调用extractStreamData的电话失败并出现以下情况:

No instance for (Colour a1)
arising from a use of `extractStreamData'
The type variable `a1' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Colour ColourRGB -- Defined at test.hs:20:10
instance Colour ColourGrey -- Defined at test.hs:17:10
In the second argument of `($)', namely
`extractStreamData someGreys'
In a stmt of a 'do' block: print $ extractStreamData someGreys
In the expression:
do { print $ extractStreamData (someColours :: ColourStream);
print $ extractStreamData someGreys }

对我来说,这意味着 Haskell 无法推断使用哪个实例(用于颜色的实例或用于灰度的实例)。这样可以吗?如果是这样,我将如何解决这个问题?


n.b. ColourGrey 的定义和ColourRGB超出了我的影响范围(它们是外部库的一部分)。因此任何建议都需要对这两种类型求模。我不想乱搞 ColourStream ,或者,因为它被用在很多其他地方。

我需要访问“原始”列表的原因是这样我可以处理类似 map 的内容。等等。如果有一个我还没有学会的巧妙技巧,它将使得ColourStream可迭代,那么我想这会起作用... </thinking aloud>

最佳答案

问题是 Haskell 看到 extractStreamData 并意识到它将返回一些 Colour a => a,但随后你将其通过管道传输到 show 中,因此它也意识到aShow 的一个实例,但之后就没有提及 a

这意味着 Haskell 无法确定 a 应该是什么类型。解决方案只是帮助类型检查器并添加一些签名

print $ (extractStreamData someGreys :: [ColourGrey])

就这样。

但是你的类型类实例有点......令人担忧。如果您将 ColourGray 传递给 ColourRGB 实例,会发生什么?在运行时在几乎不知道信息的情况下爆炸是一个糟糕的 react 。

请记住,类型类只是进行[真正增强]基于类型的重载的一种方法。真的,看起来你想要丹尼尔·瓦格纳拥有的东西或类似的东西

translateRGB :: ColourRGB -> ColourGrey
translateGrey :: ColourGrey -> ColourRGB

然后让您的实例更像

instance Colour ColourGrey where
extractStreamData (Greys x) = x
extractStreamData (Colours x) = map translateRGB x

这样您只需选择是否要将流视为 ColourGreyColourRGB 并使用它。现在,当您使用 extractStreamData 时,您不会首先尝试找出流中的内容。

关于haskell - 跨类型类的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19712223/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com