“无法推断".多参数类型类上的错误 [英] "Could not deduce" error on multi-parameter type class

查看:102
本文介绍了“无法推断".多参数类型类上的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有此代码:

{-# LANGUAGE MultiParamTypeClasses #-}
import System.Random (RandomGen(..))

class RandomGen gen => Shadow gen light where
    shadowRay :: gen -> light -> Float
    eval      :: light -> Float

我得到那个错误:

[1 of 1] Compiling Main             ( problem.hs, problem.o )

problem.hs:6:5: error:
    * Could not deduce (Shadow gen0 light)
      from the context: Shadow gen light
        bound by the type signature for:
                   eval :: Shadow gen light => light -> float -> float
        at problem.hs:6:5-40
      The type variable `gen0' is ambiguous
    * In the ambiguity check for `eval'
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      When checking the class method:
        eval :: forall gen light.
                Shadow gen light =>
                forall float. light -> float -> float
      In the class declaration for `Shadow'

这是GHC 7.10+中的问题.在工作之前.如果我将"gen"参数添加到"eval",则有一个解决方法,例如:

This is problem from GHC 7.10+. Before it was working. There is a fix if I add "gen" parameter to "eval", like:

eval :: gen -> light -> Float

但是我不想添加一个不会使用的新值参数.是否有其他类型的类型解析方式?

But I don't want to add a new value parameter which will not be used. Is there some kind of other way for type resolution?

推荐答案

问题是eval不使用gen,因此仅对其类型进行专门化不足以决定在选择该类型时使用哪个gen.要使用的Shadow实例.一种可能的解决方案是使用功能依赖性,以强制每个light选择只有一个gen:

The problem is that eval does not use gen, and so specialising its type is not enough to decide which gen to use when picking the Shadow instance to use. One possible solution is using a functional dependency to enforce that there will be only one gen for each choice of light:

{-# LANGUAGE FunctionalDependencies #-}

class RandomGen gen => Shadow gen light | light -> gen where
    shadowRay :: gen -> light -> Float
    eval      :: light -> Float

但是,您可能不希望或不需要以这种方式耦合lightgen.在这种情况下,您可能要考虑从类型类中删除gen的相反选择-如果genlight不相关,则不需要多参数类型类来将它们相关:

It is possible, however, that you don't want or need to couple light and gen in this manner. In that case, you might want to consider the opposite alternative of removing gen from the type class -- if gen and light aren't related, you don't need a multi-parameter type class to relate them:

class Shadow light where
    shadowRay :: RandomGen gen => gen -> light -> Float
    eval      :: light -> Float

这篇关于“无法推断".多参数类型类上的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆