如何在不同类型的注释中引用相同的类型变量?

时间:2014-11-13 10:19:37

标签: haskell

说我有以下内容:

import Control.Monad.Random

foo :: IO Float
foo = fmap realToFrac getRandom

GHC正确地抱怨不知道getRandom的类型;我可以通过

解决这个问题
foo = fmap realToFrac (getRandom :: IO Double)

然而,请考虑我所拥有的情况:

foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac getRandom

我不能只做

foo = fmap realToFrac (getRandom :: m Double)

我必须重复MonadRandom约束:

foo = fmap realToFrac (getRandom :: MonadRandom m => m Double)

由于存在大量约束,这将导致大量额外输入。我宁愿不必那样做。我知道我可以使用ScopedTypeVariables

{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad.Random

foo :: MonadRandom m => m Float
foo = do
    x :: Double <- getRandom
    return (realToFrac x)

但这同样冗长,而且我无法在所有这些情况下应用它。

我也知道PartialTypeSignatures提案。我认为这可能允许我这样做:

foo = fmap realToFrac (getRandom :: _ Double)

但是我对其(长)描述的扫描并不完全清楚。不幸的是,PartialTypeSignatures尚未准备好进入黄金时段,因此尚未包含在GHC的发布版本中。

我显然欢迎提出其他建议,但我能想到的一个解决方案可以通过以下方式识别mn

foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac (getRandom :: n Double)

这种事情有可能吗?

1 个答案:

答案 0 :(得分:8)

你的直觉是正确的:ScopedTypeVariables是这项工作的正确延伸:

{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad.Random

foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac (getRandom :: m Double)