首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为state-monad方法提供泛型类型

如何为state-monad方法提供泛型类型
EN

Stack Overflow用户
提问于 2019-05-17 07:44:24
回答 1查看 79关注 0票数 0

我正在尝试为状态monad创建一个function,它可以在a中接收一个泛型类型:

newtype State s a=State { runstate::s->(s,a) }

我只想绑定第一种类型的runstate::s->(s,a),然后决定a应该是什么:

所以,而不是像这样:

代码语言:javascript
复制
f::Int->(Int,String)
f x | x>3 = (x, "bigger then 3")
    |otherwise =(x,"smaller then 3")

make::State Int String
make =State f

我怎样才能做到:

代码语言:javascript
复制
makeFree::State Int a
makeFree=State ....

你可能想知道我为什么要那样做。虽然我知道state的类型,但我希望计算结果有所变化。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-17 09:24:13

你的想法还不完全清楚,但根据这些评论,以下是一些建议。

参数化函数

如前所述,f返回(Int, String),您不能仅仅改变这一点。然而,你能做的是把它参数化:

代码语言:javascript
复制
f' :: a -> a -> Int -> (Int, a)
f' bigger smaller x | x > 3 = (x, bigger)
                    | otherwise = (x, smaller)

这个变体不再返回(Int, String),而是返回(Int, a)。然而,您所付出的代价是您必须提供biggersmaller作为参数。稍后我们将返回到这一点,但在此之前,我们可以将具有通用类型s -> (s, a)的任何函数转换为一个State s a值:

代码语言:javascript
复制
make' :: (s -> (s, a)) -> State s a
make' fn = State fn

现在可以部分应用f'来改变类型:

代码语言:javascript
复制
*Q56181862> :t make' $ f' "bigger than 3" "smaller than 3"
make' $ f' "bigger than 3" "smaller than 3" :: State Int [Char]
*Q56181862> :t make' $ f' True False
make' $ f' True False :: State Int Bool

在上述GHCi示例的第一个示例中,类型为State Int String,而第二个示例具有State Int Bool类型。

返回

从其他评论来看,您似乎希望在State Int StringState Int (IO String)之间有所变化。虽然您可以使用上面的技术实现这一点,但是您也可以在函数本身中使用return

代码语言:javascript
复制
f'' :: Monad m => Int -> (Int, m String)
f'' x | x > 3 = (x, return "bigger than 3")
      | otherwise = (x, return "smaller than 3")

这只改变了单变量,而不是“返回类型”String。您可以向Haskell的类型系统提供足够的提示,以通知它m应该是IO

代码语言:javascript
复制
*Q56181862> :t make' $ f'' :: State Int (IO String)
make' $ f'' :: State Int (IO String) :: State Int (IO String)

如果不想在IO中运行计算,可以在Identity中运行它,这也是一个Monad

代码语言:javascript
复制
*Q56181862 Control.Monad.Identity> :t make' $ f'' :: State Int (Identity String)
make' $ f'' :: State Int (Identity String) :: State Int (Identity String)

现在可以运行计算,并使用StringIdentity中提取runIdentity

函子

如果你把State s也变成函子,你可以把StringIdentity中拉出来。

代码语言:javascript
复制
*Q56181862 Control.Monad.Identity> :t fmap runIdentity $ make' $ f''
fmap runIdentity $ make' $ f'' :: State Int String

最简单的方法是使用DeriveFunctor GHC扩展:

代码语言:javascript
复制
newtype State s a = State { runstate :: s -> (s, a) } deriving Functor

...or,你可以用mtl包的Control.Monad.State.Lazy .

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56181862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档