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

Jos*_*lin 5 haskell

说我有以下内容:

import Control.Monad.Random

foo :: IO Float
foo = fmap realToFrac getRandom
Run Code Online (Sandbox Code Playgroud)

GHC正确地抱怨不知道其类型getRandom; 我可以解决这个问题

foo = fmap realToFrac (getRandom :: IO Double)
Run Code Online (Sandbox Code Playgroud)

但是,请考虑我所拥有的情况:

foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac getRandom
Run Code Online (Sandbox Code Playgroud)

我做不到

foo = fmap realToFrac (getRandom :: m Double)
Run Code Online (Sandbox Code Playgroud)

我必须重复这个MonadRandom约束:

foo = fmap realToFrac (getRandom :: MonadRandom m => m Double)
Run Code Online (Sandbox Code Playgroud)

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

{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad.Random

foo :: MonadRandom m => m Float
foo = do
    x :: Double <- getRandom
    return (realToFrac x)
Run Code Online (Sandbox Code Playgroud)

但这也很冗长,而且我不能在所有这些情况下应用它.

我也知道这个PartialTypeSignatures提议.我这可能让我这样做:

foo = fmap realToFrac (getRandom :: _ Double)
Run Code Online (Sandbox Code Playgroud)

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

我显然欢迎其他的建议,而是一个解决这个问题,我能想到的是一些方法来识别mn在以下几点:

foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac (getRandom :: n Double)
Run Code Online (Sandbox Code Playgroud)

这种事可能吗?

gal*_*ais 8

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

{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad.Random

foo :: (Functor m, MonadRandom m) => m Float
foo = fmap realToFrac (getRandom :: m Double)
Run Code Online (Sandbox Code Playgroud)