You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:54:58