当前位置:  开发笔记 > 编程语言 > 正文

隐藏状态monad的类型参数

如何解决《隐藏状态monad的类型参数》经验,为你挑选了1个好方法。

我试图State在一个新类型中隐藏monad 的类型参数,但是我很难将存在的限定sg要提供的一致evalFoo.我已经试过ExistentialQuantification,GADTsRankNTypes,但有这些扩展是如何工作的一个公认非常缺乏了解.

惯用的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

Cactus.. 6

Foo构造函数类型中的存在量化意味着对于每个类型的值Foo,都有一些RandomGen用作其状态的实例.你想相反,虽然:你想给定任何值foo :: Foo,和任何情况下gRandomGen,你可以使用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

是的,不是0.78;)



1> Cactus..:

Foo构造函数类型中的存在量化意味着对于每个类型的值Foo,都有一些RandomGen用作其状态的实例.你想相反,虽然:你想给定任何值foo :: Foo,和任何情况下gRandomGen,你可以使用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

是的,不是0.78;)

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有