3

作为一个训练练习,我编写了一个多态函数来确定给定数字是单个数字还是所有数字列表的素数:

{-# LANGUAGE FlexibleInstances #-}
class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo (Integer) where
    ispt n d = 0 /= (rem n d)
instance PrimeTo ([Integer]) where
    ispt n [] = True
    ispt n (x:xs) = (ispt n x) && (ispt n xs)

为了让它工作,我不得不使用 FlexibleInstances,我对此很满意,但很好奇。

据我了解,在严格的 Haskell 98 下,我需要在实例定义中添加一个类型描述符T

class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo (T Integer) where
    ispt n d = 0 /= (rem n d)
instance PrimeTo (T [Integer]) where
    ispt n [] = True
    ispt n (x:xs) = (ispt n x) && (ispt n xs)

但我不知道用什么代替“T”,我什至不知道这在 Haskell 98 下是否可行。

所以:

  1. 在 Haskell 98 下这甚至可能吗?
  2. 如果是这样,T 会使用什么?
4

1 回答 1

4

T可以是Integer[],如下所示:

class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo Integer where
    ispt n d = 0 /= (rem n d)
instance PrimeToList a => PrimeTo [a] where
    ispt = isptList  -- see below

由于最后一个只能是 about [a],我们需要一个辅助类PrimeToList。这是附加的帮助程序类和实例:

class PrimeToList a where
    isptList :: Integer -> [a] -> Bool

instance PrimeToList Integer where
    isptList n []     = True
    isptList n (x:xs) = ispt n x && isptList n xs

顺便说一句,我会使用以下方法重写最后一个定义all

    isptList n = all (ispt n)

以上显示了一般技术。在您的特定情况下,您可能可以避免使用助手类并使用

class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo Integer where
    ispt n d = 0 /= (rem n d)
instance PrimeTo a => PrimeTo [a] where
    ispt n = all (ispt n)

这也将定义PrimeTo [[Integer]],PrimeTo [[[Integer]]]等等,因此它不像前一个那样是完美的替代品。

于 2020-07-05T11:47:14.360 回答