【问题标题】:"could not deduce ... from the context ...", despite context holding what's necessary“无法从上下文中推断出......”,尽管上下文包含必要的内容
【发布时间】:2015-02-01 15:11:20
【问题描述】:

以下文件编译失败:

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module AltMonad.Monoid where

import AltMonad.Category
import Prelude (curry)

class Category c
   => Monoid i p c m where
  mid   :: i `c` m
  mcomb :: (m `p` m) `c` m

class Monoid () (,) (->) m
   => HaskellMonoid m where
  empty  :: m
  append :: m -> m -> m

instance Monoid () (,) (->) m
      => HaskellMonoid m where
  empty  = mid ()
  append = curry mcomb

它给出了错误:

[3 of 3] Compiling AltMonad.Monoid  ( AltMonad\Monoid.hs, interpreted )

AltMonad\Monoid.hs:24:12:
    Could not deduce (Monoid () p0 (->) m)
      arising from a use of `mid'
    from the context (Monoid () (,) (->) m)
      bound by the instance declaration
      at AltMonad\Monoid.hs:(22,10)-(23,24)
    The type variable `p0' is ambiguous
    Relevant bindings include
      empty :: m (bound at AltMonad\Monoid.hs:24:3)
    In the expression: mid ()
    In an equation for `empty': empty = mid ()
    In the instance declaration for `HaskellMonoid m'

AltMonad\Monoid.hs:25:18:
    Could not deduce (Monoid i0 (,) (->) m)
      arising from a use of `mcomb'
    from the context (Monoid () (,) (->) m)
      bound by the instance declaration
      at AltMonad\Monoid.hs:(22,10)-(23,24)
    The type variable `i0' is ambiguous
    Relevant bindings include
      append :: m -> m -> m (bound at AltMonad\Monoid.hs:25:3)
    In the first argument of `curry', namely `mcomb'
    In the expression: curry mcomb
    In an equation for `append': append = curry mcomb
Failed, modules loaded: AltMonad.Category, AltMonad.Hask.

在我看来,我给出了正确的上下文,但我不知道如何让 GHC 相信这一点。


相关文件:

AltMonad.Category

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeSynonymInstances #-}
module AltMonad.Category where

import AltMonad.Hask

class Category cat where
  id  :: cat a a
  (.) :: b `cat` c -> a `cat` b -> a `cat` c

instance Category Hask where
  id    = \x -> x
  g . f = \x -> g (f x)

AltMonad.Hask

{-# LANGUAGE NoImplicitPrelude #-}
module AltMonad.Hask where

type Hask = (->)

【问题讨论】:

  • This 有同样的问题。

标签: haskell types functional-programming ghc typeclass


【解决方案1】:

发生此错误是因为当您调用mid () 时,它的类型为Monoid () p0 (->) m => i -> m,并且没有任何限制p0 成为您选择的特定p,因为p0 没有出现在右侧类型签名中=> 的一侧。解决此问题的一种方法是通过 FunctionalDependencies 扩展:

-- ...

class Category c => Monoid i p c m | m -> p where
    mid   :: c i m
    mcomb :: c (p m m) m

-- ...

instance Monoid () (,) (->) m => HaskellMonoid m where
    empty  = mid ()
    append = curry mcomb

但是,这不适用于append,因为变量i 现在必须受到约束。这只是意味着我们需要让它依赖于我们对m 的选择:

class Category c => Monoid i p c m | m -> i, m -> p where
    -- ...

现在它会编译。这是否是你想要做的,我不知道,但我知道它会让你的代码编译。

【讨论】:

  • 谢谢!我以前没有使用过 FunctionalDependencies,但它解决了我的问题。我会更全面地研究它。
  • @BertieWheen FunctionalDependencies 扩展很有用,但您可能会从经常可以替换它的 TypeFamilies 扩展中获得更多好处。它有点复杂,但它允许更大的灵活性。例如,使用这些函数依赖项,您将只能更改 Category 实例,而不是 ip 变量。从本质上讲,它限制了类中的多态性数量,以便它可以解决约束,但这显然意味着它不那么通用。
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 2018-11-08
  • 1970-01-01
  • 2015-08-28
  • 2019-05-14
相关资源
最近更新 更多