GHC类型推断困难

gat*_*ado 5 haskell type-inference typeclass ghc associated-types

问题.有没有办法让这个代码没有明确的类型签名?

代码.首先,我有一个实践中更好的替代MonadTrans课程,受到启发Data.Newtype.看起来像这样,

{-# LANGUAGE FlexibleContexts, TypeFamilies #-}

module Alt.Control.Monad.Trans where

import Control.Monad

class (Monad , Monad (BaseMonad )) => MonadTrans ( :: * -> *) where
    type BaseMonad  :: * -> *
    lift :: (BaseMonad ) ? ->  ?
Run Code Online (Sandbox Code Playgroud)

然后,我有一个A方法的类foo,如果一个基础monad M是一个A,那么任何转换的monad T M也是一个A.在代码中,

class A  where
    foo :: String ->  ()

instance (A (BaseMonad ), MonadTrans ) => A  where
    foo n = lift $ foo n
Run Code Online (Sandbox Code Playgroud)

但是,如果我现在想要创建一个foo替换它的第一个参数的快捷方式,那么我需要一个显式类型签名,或者编译器的上下文堆栈溢出.

minimize_call :: A  =>  ()
minimize_call = foo "minimize"
Run Code Online (Sandbox Code Playgroud)

可能的信息,以帮助推断.假设我们有一个相关的类型B :: * -> *.我在想,我要告诉编译器B满足B t /= t,B (B t) /= B t等等即B是某种"单调" -即追逐相关类型相当于消除NEWTYPE包装,它应该知道,它不能删除NEWTYPE永远的包装,因此加入A签名的上下文是必要的.

Dan*_*her 3

是的,有办法。提供 , 的基础实例A,并将其添加NoMonomorphismRestriction到语言编译指示中(除了还需要的FlexibleInstancesUndecidableInstances)。

\n\n

但是,该类A将无法使用。编译器无法知道永远不会存在MonadTrans带有以下内容的实例BaseMonad m = m。因此,它永远无法选择实例,因为它不知道是使用此处的实例还是另一个实例。

\n\n
{-# LANGUAGE FlexibleContexts, TypeFamilies, FlexibleInstances, UndecidableInstances, NoMonomorphismRestriction #-}\n\nmodule Trans (MonadTrans(..), A(..), minimize_call) where\n\nimport Control.Monad\n\nclass (Monad m, Monad (BaseMonad m)) => MonadTrans (m :: * -> *) where\n    type BaseMonad m :: * -> *\n    lift :: (BaseMonad m) \xce\xb1 -> m \xce\xb1\n\nclass A m where\n    foo :: String -> m ()\n\n\ndata Foo a = Bork\n\ninstance Monad Foo where\n    return _ = Bork\n    _ >>= _ = Bork\n\ninstance A Foo where\n    foo _ = Bork\n\n\ninstance (A (BaseMonad m), MonadTrans m) => A m where\n    foo n = lift $ foo n\n\n-- minimize_call :: A m => m ()\nminimize_call = foo "minimize"\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用 ghc 6.12、7.0、7.2 和 7.4 进行编译。没有签名,minimize_call必须得到单态类型,除非MR被关闭。无论如何这都是行不通的,因为约束A m是不可默认的。因此必须关闭 MR。但是类型检查器仍然追逐自己的尾巴,试图证明约束是可以满足的。仅使用举升实例,它不能。如果你提供一个锚点,它就可以。

\n\n

但提供类型签名要好得多。

\n