首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在haskell中增加环境的应用程序

在haskell中增加环境的应用程序
EN

Stack Overflow用户
提问于 2015-05-08 14:20:24
回答 1查看 164关注 0票数 4

我想知道是否有一个Applicative可以跟踪发生了多少个应用程序操作。我试图按以下方式实现:

代码语言:javascript
复制
import Control.Applicative

main :: IO ()
main = print $ run 1 $ (,,,) <$> FromInt id <*> FromInt id <*> FromInt id <*> FromInt id

data FromInt a = FromInt (Int -> a)

run :: Int -> FromInt a -> a
run i (FromInt f) = f i

instance Functor FromInt where
  fmap g (FromInt f) = FromInt (g . f)

instance Applicative FromInt where
  pure a = FromInt (const a)
  FromInt f <*> FromInt g = FromInt (\i -> f i (g (i + 1)))

但是,这当然是行不通的。如果我们在文件上调用runhaskell,我们会得到以下内容:

代码语言:javascript
复制
(1,2,2,2)

我想要的是:

代码语言:javascript
复制
(1,2,3,4)

我看到人们通过将需求增加到实际数据中来实现这一效果( yesod-forms就是这样实现其表单风格的)。这或多或少地使用了State上的一个变体,如果人们不使用特定的辅助函数(我认为yesod函数称为mhelper),就可以打破假定的不变量。我想知道是否可以像我尝试的那样将增量拖到应用程序实例中。这将使违反这一特定不变的不可能。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-08 14:58:28

(,) aApplicative,而aMonoid。我们可以使用(,) (Sum Int)与其他应用程序组合Data.Functor.Compose,并得到一个应用程序,它允许我们在运行计算之前估计分配给计算的“成本”。

要计算这些步骤,我们需要一个基本应用程序中的lift函数,它总是分配1的成本:

代码语言:javascript
复制
module Main where

import Data.Monoid
import Control.Applicative
import Data.Functor.Compose

type CountedIO a = Compose ((,) (Sum Int)) IO a

-- lift from IO
step :: IO a -> CountedIO a
step cmd = Compose (Sum 1, cmd)

countSteps :: CountedIO a -> Int
countSteps = getSum . fst . getCompose

exec :: CountedIO a -> IO a
exec =  snd . getCompose

program :: CountedIO () 
program = step (putStrLn "aaa") *>  step (putStrLn "bbb") *> step (putStrLn "ccc")

main :: IO ()
main = do
    putStrLn $ "Number of steps: " ++ show (countSteps program)
    exec program 

为了获得更好的安全性,我们可以将组合的辅助函数隐藏在newtype后面,而不是导出构造函数,而只导出step函数。

(使用pure创建的操作成本为0,不计为步骤。)

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

https://stackoverflow.com/questions/30126111

复制
相关文章

相似问题

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