【发布时间】:2012-02-15 21:49:23
【问题描述】:
问题。有没有办法让这段代码在没有显式类型签名的情况下工作?
代码。首先,我有一个实践中更好的替代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 ????) α -> ???? α
然后,我有一个带有方法foo 的类A,如果某个基本单子M 是A,那么任何转换后的单子T M 也是一个A。在代码中,
class A ???? where
foo :: String -> ???? ()
instance (A (BaseMonad ????), MonadTrans ????) => A ???? where
foo n = lift $ foo n
但是,如果我现在想为 foo 创建一个快捷方式并替换它的第一个参数,那么我需要一个显式类型签名,否则编译器的上下文堆栈会溢出。
minimize_call :: A ???? => ???? ()
minimize_call = foo "minimize"
有助于推理的可能信息。假设我们有一个关联类型B :: * -> *。我在想我想告诉编译器B 满足B t /= t、B (B t) /= B t 等,即B 在某种程度上是“单调的”——追逐关联类型相当于删除新类型包装器,它应该知道它不能永远删除 newtype 包装器,因此需要将上下文 A 添加到签名中。
【问题讨论】:
-
抱歉,我应该费心记住 为什么 我切换到备用
MonadTrans... 现在,假设它产生更清晰的代码,但我认为有一个更重要的原因。 -
有趣的问题。你为什么不想要一个显式的类型签名呢?
minimize_call不是必须是某个固定值,而不是多态常量(或者也许你可以让它成为多态,我不确定)?如果它有一些单一的固定类型,我宁愿记录它,如果没有,我宁愿记录那个。强迫读者在头脑中进行整个程序分析以找出minimize_call的类型似乎有点适得其反。 -
@Ben,确实,在这种情况下,拥有
minimize_call的类型签名是一种很好的做法。但是,类型推断被破坏表明出现了问题(设计、编译器或与编译器的通信),并且可能会导致问题,更不用说难以理解的错误消息了。
标签: haskell ghc type-inference typeclass associated-types