“Could not deduce” error on multi-parameter type class

与世无争的帅哥 提交于 2019-12-24 05:45:35

问题


I have this code:

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

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

and I get that error:

[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'

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?


回答1:


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

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


来源:https://stackoverflow.com/questions/41592832/could-not-deduce-error-on-multi-parameter-type-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!