什么“Contraint不比实例头部更小”意味着如何解决它 [英] What "Contraint is no smaller than the instance head" means and how to solve it

查看:107
本文介绍了什么“Contraint不比实例头部更小”意味着如何解决它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一些类似于:


$ b

  { - #LANGUAGE FlexibleContexts,FlexibleInstances# - } 

import Data.ByteString.Char8(ByteString,pack)
import Data.Foldable(可折叠)

class(显示a)=>行a where
rRepr :: a - > [ByteString]
rRepr =(:[])。包。显示

实例(可折叠f,显示(f a))=>行(fa)其中
rRrr = const []

表示 fa 实例化如果 f 实例化可折叠 fa 实例化显示。当我运行ghc时,我得到:

 约束不小于约束中的实例头部
:Show(fa )
(使用-XUndecidableInstances来允许这样做)
在'行(fa)'的实例声明中

我有两个问题:


  • 在错误中小意味着什么?问题是什么? li>
  • 在不使用 UndecidableInstances

$ b的情况下定义我想要的内容的正确方法是什么$ b

解决方案

让我们玩编译器:我们有一个类型(fa)它是 Rows 约束的有效满足者。为此,我们需要派发(f a)满足 Show(f a)的证明。这不是一个问题,除非有人写了一个

 实例Rows(f a)=>显示(f a)其中... 

在这种情况下,我回到了我开始的地方。像这样编码一个无限循环是愚蠢的,但Haskell静态地确保它实际上是不可能的,除非你要求 UndecidableInstances



通常,Haskell确保解析器追踪的每个步骤至少通过1个构造函数来减少类型的大小。这导致了一个非常简单的结构归纳证明,我们最终将得到一个在有限数量的分辨率下的裸类型。



这是过分限制的,显然有些实例即使不立即减少构造树,分辨率步骤也是有意义的,有用的和完整的。这种类型的总体限制适用于Agda和Coq等语言,并且通常将您的算法操作为通过结构化归纳进行的算法,这往往是一种说明性挑战。






那么我们该如何解决?一种方法是在定义中使用像 Show1这样的实例丢失显示约束。 / code> from prelude-演员的。

  class Show1 f where ... 
show1 ::(Show1 f,Show a)=> f a - >字符串 - 不是实例定义!

然后有实例(Foldable f,Show1 f,Show a)= >行(f a)其中... 它在我的测试中起作用。您可以将默认实例编写为独立函数。

a - > [ByteString]
defRRepr =(:[])。包。显示

并且在写一个的实例定义时使用它显示




另一种解决方案是使用 newtype

  instance(Foldable f,Show)使用$ c> wrappers来允许Haskell看到一个图层 (fa))=>行(FoldableRow f a)其中
rRepr = const []。 unFR

newtype FoldableRow f a = FR {unFR :: f a}派生(显示)


I would like to write something like:

{-# LANGUAGE FlexibleContexts,FlexibleInstances #-}

import Data.ByteString.Char8 (ByteString,pack)
import Data.Foldable (Foldable)

class (Show a) => Rows a where
    rRepr :: a -> [ByteString]
    rRepr = (:[]) . pack . show

instance (Foldable f,Show (f a)) => Rows (f a) where
    rRepr = const []

meaning that f a instantiate Rows if f instantiate Foldable and f a instantiate Show. When I run ghc I get:

Constraint is no smaller than the instance head
  in the constraint: Show (f a)
(Use -XUndecidableInstances to permit this)
In the instance declaration for `Rows (f a)'

I have two questions:

  • what "smaller" means in the error and what is the problem?
  • what is the right way to define what I want without using UndecidableInstances?

解决方案

Let's play compiler: we have a type (f a) we'd like to see if it is a valid satisfier of a Rows constraint. To do so, we need to dispatch a proof that (f a) satisfies Show (f a) as well. This isn't a problem unless someone writes an

 instance Rows (f a) => Show (f a) where ...

in which case I'm back where I began. Encoding an infinite loop like this is sort of foolish, but Haskell statically ensures that it's actually impossible unless you ask for UndecidableInstances.


Normally Haskell ensures that each step of a "resolution chase" reduces the size of the type by at least 1 constructor. This leads to a really simple proof by structural induction that we'll end up with a bare type in a finite number of resolutions.

This is overly restrictive, clearly some instance resolution steps are meaningful, useful, and total even if they don't immediately reduce the constructor tree. This same kind of totality restriction applies in languages like Agda and Coq and often it's a bit of an illustrative challenge to manipulate your algorithm into one which proceeds by structural induction.


So how can we fix it? One way is to lose the Show constraint on the class definition use an instance like Show1 from prelude-extras.

class Show1 f where ...
show1 :: (Show1 f, Show a) => f a -> String  -- not an instance definition!

and then have instance (Foldable f, Show1 f, Show a) => Rows (f a) where ... which works in my testing. You can then write a default instance as a standalone function.

defRRepr :: Show a => a -> [ByteString]
defRRepr = (:[]) . pack . show

and use it whenever writing an instance definition for a Showable thing.


The other solution is to use newtype wrappers to allow Haskell to see that a "layer" of resolution has been removed.

instance (Foldable f, Show (f a)) => Rows (FoldableRow f a) where
    rRepr = const [] . unFR

newtype FoldableRow f a = FR { unFR :: f a } deriving (Show)

这篇关于什么“Contraint不比实例头部更小”意味着如何解决它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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