Почему этот тип не проверяет?

Это toy-example.hs:

{-# LANGUAGE ImpredicativeTypes #-}

import Control.Arrow

data From = From (forall a. Arrow a => a Int Char -> a [Int] String)

data Fine = Fine (forall a. Arrow a => a Int Char -> a () String)

data Broken = Broken (Maybe (forall a. Arrow a => a Int Char -> a () String))

fine :: From -> Fine
fine (From f) = Fine g
  where g :: forall a. Arrow a => a Int Char -> a () String
        g x = f x <<< arr (const [1..5])

broken :: From -> Broken
broken (From f) = Broken (Just g) -- line 17
  where g :: forall a. Arrow a => a Int Char -> a () String
        g x = f x <<< arr (const [1..5])

И вот что думает об этом ghci:

GHCi, version 7.0.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> :l toy-example.hs 
[1 of 1] Compiling Main             ( toy-example.hs, interpreted )

toy-example.hs:17:32:
    Couldn't match expected type `forall (a :: * -> * -> *).
                                  Arrow a =>
                                  a Int Char -> a () String'
                with actual type `a0 Int Char -> a0 () String'
    In the first argument of `Just', namely `g'
    In the first argument of `Broken', namely `(Just g)'
    In the expression: Broken (Just g)
Failed, modules loaded: none.

Почему fine проверяет тип, а broken нет?

Как заставить broken проверять тип?

(В моем реальном коде я могу добавить параметр типа a к Broken, если это необходимо, вместо универсального количественного определения внутри конструктора, но я хотел бы избежать этого, если это возможно.)


Изменить: если я изменю определение Broken на

data Broken = Broken (forall a. Arrow a => Maybe (a Int Char -> a () String))

затем broken проверяет тип. Ура!

Но если я добавлю следующую функцию

munge :: Broken -> String
munge (Broken Nothing) = "something"  -- line 23
munge (Broken (Just f)) = f chr ()

то я получаю сообщение об ошибке

toy-example.hs:23:15:
    Ambiguous type variable `a0' in the constraint:
      (Arrow a0) arising from a pattern
    Probable fix: add a type signature that fixes these type variable(s)
    In the pattern: Nothing
    In the pattern: Broken Nothing
    In an equation for `munge': munge (Broken Nothing) = "something"

Как мне заставить munge также проверять тип?

2-е редактирование: в моей реальной программе я заменил конструктор Broken (Maybe ...) конструкторами BrokenNothing и BrokenJust ... (уже были другие конструкторы), но мне любопытно, как в этой ситуации должно работать сопоставление с образцом.


person dave4420    schedule 27.05.2011    source источник
comment
Перемещение поля позволяет выйти на один уровень наружу, что позволяет работать этому: data Broken = Broken (forall a. Arrow a => Maybe (a Int Char -> a () String)). Я подозреваю, что в разделе 7.8 руководства GHC рассказывается, почему ваша версия не работает, точное обессахаривание фораллов - это не то, в чем я разбираюсь.   -  person stephen tetley    schedule 27.05.2011
comment
Это устраняет эту проблему, но я больше не могу сопоставлять шаблоны с Nothing.   -  person dave4420    schedule 27.05.2011


Ответы (1)


ImpredicativeTypes оставляет вас на довольно шаткой почве, которая в любом случае меняется от версии к версии GHC - они изо всех сил пытаются найти формулировку непредикативности, которая надлежащим образом уравновешивает мощность, простоту использования и простоту реализации.

В этом конкретном случае попытка поместить количественный тип внутри Maybe, который является типом данных, явно не определенным для такого поведения, действительно сложна, поэтому я бы посоветовал вместо этого использовать настраиваемые конструкторы, как вы упомянули.

Я думаю, что вы можете исправить munge выше, переконструировав аргумент в Broken в RHS, в то время, когда тип, который он используется, будет известен, например:

munge (Broken x@(Just _)) = fromJust x chr ()

Однако это довольно некрасиво.

person GS - Apologise to Monica    schedule 27.05.2011