gpt4 book ai didi

haskell - 跨类型类的模式匹配

转载 作者:行者123 更新时间:2023-12-02 04:46:27 26 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 实例,会发生什么情况?在运行时爆炸而几乎不知道信息是一个糟糕的响应。

请记住,类型类只是一种实现[真正增强]基于类型的重载的方式。真的,看起来你想要 Daniel Wagner 拥有的东西或类似的东西

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/

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