我正在尝试在新类型中隐藏State
monad的类型参数,但我很难将存在限定的s
与g
统一到为evalFoo
提供。我尝试过使用ExistentialQuantification
,GADTs
和RankNTypes
,但对这些扩展的工作原理一无所知。
惯用的Haskell如何实现这种外观? 谢谢!
{-# LANGUAGE GADTs #-}
import Control.Monad.State
import System.Random
data Foo a where
Foo :: RandomGen s => State s a -> Foo a
evalFoo :: RandomGen g => Foo a -> g -> a
evalFoo (Foo m) g = evalState m g
目标是实现这样的目标,但能够提供RandomGen
的任何实例:
myRNG :: Foo Double
myRNG = Foo $ do
u <- state random
return u
Prelude> evalFoo myRNG (mkStdGen 123)
0.7804356004944119
答案 0 :(得分:6)
Foo
构造函数类型中的存在量化意味着对于Foo
类型的每个值,都会将RandomGen
的某个实例用作其状态。但是,您希望相反:您想要foo :: Foo
的任何值g
以及RandomGen
的任何实例g
,您可以使用foo
作为{-# LANGUAGE Rank2Types #-}
import Control.Monad.State
import System.Random
newtype Foo a = MkFoo{ unFoo :: forall g. (RandomGen g) => State g a }
evalFoo :: RandomGen g => Foo a -> g -> a
evalFoo = evalState . unFoo
由myRNG :: Foo Double
myRNG = MkFoo $ do
u <- state random
return u
封装的计算状态。
所以让我们写一下:
*Main> evalFoo myRNG (mkStdGen 123)
0.43927189736460226
这可以按预期使用:
if(isset($_POST["btnImport"]))
{
$uploads_dir = 'C:/wamp/www/quiz admin/uploads';
$tmp_name = $_FILES["excelFile"]["tmp_name"];
$name = $_FILES["excelFile"]["name"];
if(!empty($_FILES["excelFile"]["tmp_name"]))
{
move_uploaded_file($tmp_name, "$uploads_dir/$name");
$fileupload = $_FILES["excelFile"]["tmp_name"];
$fileName = explode(".",$_FILES["excelFile"]["name"]);
if($fileName[1]=="xls"||$fileName[1]=="xlsx")
{
$data = new Spreadsheet_Excel_Reader($uploads_dir.'/'.$name);
给
df.index.isin(sample)
是的,不是0.78;)
答案 1 :(得分:4)
这个问题就像你描述的那样。您将无法将存在包裹的随机种子与您的初始随机种子统一起来。最明显的方法是完全放弃存在量化,并使用它:
runRandomly :: RandomGen g => State g a -> g -> a
runRandomly (Foo m) g = evalState m g
在这种情况下,我认为最明显的方法没有任何问题。如果您真的想要隐藏变换器中的种子类型,Cactus's answer会显示如何正确执行此操作。
在其他一些情况下,一些类似的存在包装可以通过将种子与变换器一起包装来实现:
data Foo a where
Foo :: RandomGen s => State s a -> s -> Foo a
您可以在foldl
包中看到类似内容的示例。