首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试使Haskell记录器用于学习,但Monad实例的限制阻碍了我

尝试使Haskell记录器用于学习,但Monad实例的限制阻碍了我
EN

Stack Overflow用户
提问于 2018-01-20 23:56:13
回答 1查看 76关注 0票数 0
代码语言:javascript
复制
import Control.Monad

data Logger l a = Logger {runLogger :: (IO (),a,l)}

iologger :: (Show l)=> l->a->(a->b)->Logger l b
iologger l a f = Logger (print l,f a,l) 

instance (Show l)=>Monad (Logger l) where
  return a = iologger (show "") a id
  logger>>=f = let (_,va,vl) = runLogger logger
           in iologger vl va f

上面的代码不能编译。我想做的东西是这样的(下面的代码是F#计算表达式)

代码语言:javascript
复制
let loggedWorkflow = 
logger
    {
    let! x = 42
    let! y = 43
    let! z = x + y
    return z
    }

因此,上面的代码记录了结果

代码语言:javascript
复制
type LoggingBuilder() =
    let log p = printfn "expression is %A" p

    member this.Bind(x, f) = 
        log x
        f x

    member this.Return(x) = 
        x

但这在Haskell中不起作用,因为print需要Show限制。Writer monad也无法做到这一点,因为它是显式的。在您编写的每个代码中,您必须将tell。有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-21 00:48:08

您可以使用RebindableSyntax以任何您想要的方式重新定义(>>=)

请注意,这并不满足单数定律,除非您考虑在程序上忽略日志记录中的差异的等价关系。

这些return也有一些更多的噪音,因为没有去糖化成(>>=)let!语法。

另外,为什么不在必要的地方调用log呢?

代码语言:javascript
复制
{-# LANGUAGE RebindableSyntax #-}

import qualified Control.Monad as Monad
import Prelude (IO, Show(show), (++), putStrLn, ($), fromInteger, Int, (+))

class CMonad m where
  return :: a -> m a
  (>>=) :: Show a => m a -> (a -> m b) -> m b

log :: Show a => a -> IO ()
log x = putStrLn $ "Expression is: " ++ show x

instance CMonad IO where
  return = Monad.return
  m >>= k = m Monad.>>= \a -> log a Monad.>> k a

main :: IO Int
main = do
  x <- return (42 :: Int)
  y <- return (43 :: Int)
  z <- return (x + y)
  return z
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48358101

复制
相关文章

相似问题

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