Haskell类型签名错误求助:Int约束不符合Kind要求问题
Haskell类型错误:Int作为约束的问题
错误根源
你代码里的Int a是完全错误的语法:Haskell中Int是具体类型(kind为*,代表它是用来描述值的类型),而类型约束(=>左边的部分)需要的是类型类(比如RandomGen、Num这种,kind为* -> Constraint,即接受一个类型参数生成约束)。Int a这种写法会让编译器误以为你要把Int当作类型类来使用,自然触发错误。
修复步骤
1. 修正rollD6和rollD6InRange的类型签名
你的Roll类方法roll/rollR返回的是([Int], g),所以直接把这两个函数的返回类型指定为[Int]即可,不需要多余的多态约束:
rollD6 :: RandomGen g => Int -> ([Int], g) rollD6 times = roll Die6 times (mkStdGen 6) rollD6InRange :: RandomGen g => Int -> Int -> Int -> ([Int], g) rollD6InRange times start end = rollR Die6 times start end (mkStdGen 6)
如果确实需要保留多态(允许返回其他数值类型),可以用类型等式约束a ~ Int来明确a就是Int类型:
rollD6 :: (RandomGen g, a ~ Int) => Int -> ([a], g) rollD6 times = roll Die6 times (mkStdGen 6)
2. (可选)让Roll类支持多态返回
如果想让roll/rollR返回任意符合条件的数值类型(不只是Int),可以修改Roll类的类型签名,把返回列表的元素类型设为多态参数:
class Roll a where roll :: (RandomGen g, Num b, Random b, Eq b) => a -> Int -> g -> ([b], g) rollR :: (RandomGen g, Num b, Random b, Eq b) => a -> Int -> b -> b -> g -> ([b], g)
此时generateIntRandomsArray的多态特性就能被充分利用,返回Int、Integer等类型的随机数列表。
3. 补充缺失的Die类型定义
你的代码里用到了Die6等构造器,但没给出Die类型的定义,需要补上:
data Die = Die6 | Die4 | Die20 | Die100 deriving (Show, Eq)
完整修复后的代码示例
import System.Random (RandomGen, mkStdGen, randomR) data Die = Die6 | Die4 | Die20 | Die100 deriving (Show, Eq) class Roll a where roll :: (RandomGen g, Num b, Random b, Eq b) => a -> Int -> g -> ([b], g) rollR :: (RandomGen g, Num b, Random b, Eq b) => a -> Int -> b -> b -> g -> ([b], g) instance Roll Die where roll Die6 times = generateIntRandomsArray 1 6 times roll Die4 times = generateIntRandomsArray 1 4 times roll Die20 times = generateIntRandomsArray 1 20 times roll Die100 times = generateIntRandomsArray 1 100 times rollR Die6 times first last = generateIntRandomsArray first last times rollR Die4 times first last = generateIntRandomsArray first last times rollR Die20 times first last = generateIntRandomsArray first last times rollR Die100 times first last = generateIntRandomsArray first last times generateIntRandomsArray :: (Eq a, Random a, Num a, RandomGen g) => a -> a -> Int -> g -> ([a], g) generateIntRandomsArray start end = generate where generate 0 generator = ([], generator) generate numberElements generator = let (value, newGenerator) = randomR (start,end) generator (restOfList, finalGenerator) = generate (numberElements-1) newGenerator in (value:restOfList, finalGenerator) rollD6 :: RandomGen g => Int -> ([Int], g) rollD6 times = roll Die6 times (mkStdGen 6) rollD6InRange :: RandomGen g => Int -> Int -> Int -> ([Int], g) rollD6InRange times start end = rollR Die6 times start end (mkStdGen 6)
内容的提问来源于stack exchange,提问作者Yago
相关产品推荐
相关产品推荐

