说我有以下内容:
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的发布版本中。
我显然欢迎提出其他建议,但我能想到的一个解决方案可以通过以下方式识别m
与n
:
foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac (getRandom :: n Double)
这种事情有可能吗?
答案 0 :(得分:8)
你的直觉是正确的:ScopedTypeVariables
是这项工作的正确延伸:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad.Random
foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac (getRandom :: m Double)