整体类型类别比较

war*_*rdz 3 haskell functional-programming

目前正在通过 Codewars 复习我的 Haskell。我编写了以下代码,

import Data.Char(digitToInt)

calc :: String -> Int
calc s = sum $ map (\i -> (digitToInt i)^n) s
        where n = length s

narcissistic :: Integral n => n -> Bool
narcissistic n = calc s == n
                where s = show n
Run Code Online (Sandbox Code Playgroud)

从而产生,

Couldn't match expected type 'Int' with actual type 'n'
      'n' is a rigid type variable bound by
        the type signature for:
          narcissistic :: forall n. Integral n => n -> Bool
Run Code Online (Sandbox Code Playgroud)

据我所知,这是由于自恋函数采用 Integral 类型类(Int 或 Integer)内的输入n造成的。然而calc函数产生一个 Int。因此我无法比较calcn的结果。

因此,我的问题是,使用这些类型类的理想方法是什么,以及我如何能够实现诸如calc之类的函数,该函数可能与 Integral 类类型一起使用(由于 digitalToInt 而无法这样? )。

che*_*ner 6

calc特别返回 an Int,这意味着==也需要 an Int,但您只提供一个Integral n => n值。当然,narcissistic 可以用 an 来调用Int,但也可以用 anInteger或其他带有Integral实例的类型来调用。

为了进行比较,您需要一个通用类型。您可以同时使用toInteger :: Integral a => a -> Integer calc s获取n可以Integer直接比较的值。

narcissistic :: (Show n, Integral n) => n -> Bool
narcissistic n = toInteger (calc s) == toInteger n
     where s = show n
Run Code Online (Sandbox Code Playgroud)

请注意,这Integral并不意味着Show;您还需要将其添加到约束中。

calc但是...您无法知道从输入计算出的数字String是否适合Int; 您应该Integer首先返回 an ,然后使用fromIntegral :: (Integral a, Num b) => a -> b转变nInteger

calc :: String -> Integer
calc s = sum $ map (\i -> (fromIntegral (digitToInt i))^n) s
        where n = length s

narcissistic :: Integral n => n -> Bool
narcissistic n = calc s == fromIntegral n
                where s = show n
Run Code Online (Sandbox Code Playgroud)