【问题标题】:Applicative that increments the environment in haskell在haskell中增加环境的应用程序
【发布时间】:2015-05-08 23:04:22
【问题描述】:

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

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,我们会得到:

(1,2,2,2)

而我想要的是这样的:

(1,2,3,4)

我见过人们通过将增量需求推送到实际数据中来实现这种效果(这就是 yesod-forms 的 formlet 样式实现方式)。这或多或少使用了State 的变体,如果人们不使用特定的辅助函数(我认为yesod 称为mhelper),它允许人们打破假定的不变量。我想知道增量是否可以像我尝试做的那样被拉入应用实例。这样就不可能违反这个特定的不变量。

【问题讨论】:

  • 我不相信这是可能的,因为应用操作不能依赖于先前的结果。为此,我认为您必须有一个 monad 才能获得所需的输出。
  • 你不需要单子。 State 的应用实例工作正常,但我希望有更好的方法。

标签: haskell applicative


【解决方案1】:

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

为了计算步数,我们需要一个来自基础应用程序的提升函数,该函数始终分配成本为 1:

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 

为了更安全,我们可以将组合的应用程序隐藏在新类型后面,而不导出构造函数,只导出 step 函数。

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

【讨论】:

  • 这是一个很好的解决方案,但它最终是我试图避免做的事情。如果没有人能想出更好的方法(不需要隐藏数据构造函数来保留不变量),我会等待一段时间并接受这一点。
  • @Andrew Thaddeus Martin 我认为在保留 Applicative 定律的同时将不变量拉入 Applicative 是很困难的。如果(&lt;*&gt;) 总是增加计数,那么pure id &lt;*&gt; v = v 的规律是什么?
  • 你是对的。我正在寻找的实例被证明是不可能的。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 2017-04-20
  • 2020-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多