a ins-6ren">
gpt4 book ai didi

haskell - 在 Haskell 中声明 "subclass"

转载 作者:行者123 更新时间:2023-12-02 10:26:04 24 4
gpt4 key购买 nike

我在 Haskell 中遇到以下简单代码的问题:

import Prelude hiding (cycle).

class ICycle a where
cycle :: a -> a

instance ICycle [a] where
cycle [] = []
cycle (x:xs) = xs ++ [x]

instance ICycle Bool where
cycle True = False
cycle False = True

instance Num a => ICycle a where
cycle n = n+1

main = do
print $ cycle $ [1,2,3]
print $ cycle $ True
print $ cycle $ 42

这里前两个实例声明按预期工作,但第三个实例声明根据标志组合触发各种错误。

我知道Num a不短于ICycle a,因此编译器无法完成类型检查。在示例中,我发现可以通过将右侧设为更大的术语或首先将感兴趣的类声明为其他类的子类来避免这种情况。相反,在这里,我本质上是想将现有类声明为新类的子类。

我想知道是否有人反对这种类型类的使用。或者,如果有一个自然的解决方案。

最佳答案

对于这个特定的示例,我认为您最好使用 newtype 来包装实例:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Prelude hiding (cycle)

class ICycle a where
cycle :: a -> a

newtype Succ a = Succ { runSucc :: a }
deriving (Num, Eq, Ord, Bounded, Enum, Show, Read)

newtype Pred a = Pred { runPred :: a }
deriving (Num, Eq, Ord, Bounded, Enum, Show, Read)

instance Enum a => ICycle (Succ a) where
cycle = Succ . succ . runSucc

instance Enum a => ICycle (Pred a) where
cycle = Pred . pred . runPred

main = do
print $ cycle $ (42 :: Succ Int)
print $ cycle $ (42 :: Pred Int)

人们可以通过多种方式循环数字 - 通过 succ、通过 pred、通过加倍、通过减半。为实例使用 newtype 的优点(正如您在问题中指出的那样,使 RHS“更大”)是它让我们拥有所有这些。

标准库使用 Product 执行相同的操作。和 Sum对于幺半群

换个角度看,如果可以为 Num 定义一个新的父类(super class),为所有实例添加默认实现Num,那么您将从所有这些实现中取消该选择。可能以一种没有意义的方式。

关于haskell - 在 Haskell 中声明 "subclass",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29931647/

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