Haskell Arrows 库论文研读 - 第一弹

发布于 2024-11-13 02:32:45 字数 2742 浏览 12 评论 0

0.1 Point-free 编程

编写一个统计字符串中指定单词的个数的函数

  count w = length . filter (==w) . words
  count "hello" "hello world. hello cycoe."
2

如果要实现从一个文件读取字符串,统计单词数并输出到终端,我们尝试在两侧 加上 printreadFile

  count w = print . length . filter (==w) . words . readFile
<interactive>:33:51-58: error:
    • Couldn't match type: IO String
                     with: [Char]
      Expected: FilePath -> String
        Actual: FilePath -> IO String
    • In the second argument of ‘(.)’, namely ‘readFile’
      In the second argument of ‘(.)’, namely ‘words . readFile’
      In the second argument of ‘(.)’, namely
        ‘filter (== w) . words . readFile’

但是行不通,因为 printreadFile 带入了副作用,我们无法通过函数 组合直接去组合他们,但是我们可以借助 Monad 去进行绑定

  count w = (>>= print) .
	    liftM (length . filter (==w) . words) .
	    readFile

在 Haskell 中,副作用使用 a -> IO b 表示,可以使用以下类型同构表示

  type Kleisli m a b = a -> m b

文件读取与输出函数可以进行如下重构

  readFile :: Kleisli IO String String
  print :: Show a => Kleisli IO a ()

那么函数组合可以定义为如下函数

  (>>>) : Monad m => Kleisli m a b -> Kleisli m b c -> Kleisli m a c
  (f >>> g) a = do b <- f a
		   g b

打印文件的函数可由 >>> 进行组合

  printFile = readFile >>> print

和 Monad 的 return 函数类似, Kleisli 也有对应接口 arr 将一个普通 函数包装成 Kleisli 类型

  arr :: Monad m => (a -> b) -> Kleisli m a b
  arr f = return . f

使用这些组合子组合副作用和纯函数

  count w = readFile >>>
	    arr words >>> arr (filter (==w)) >>> arr length >>>
	    print

0.2 Arrow 类型类

Arrow 类型类表示实现了 arr>>> 接口的类型

  class Arrow arr where
    arr :: (a -> b) -> arr a b
    arr = id
    (>>>) :: arr a b -> arr b c -> arr a c
    (>>>) = flip (.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

攀登最高峰

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

daid

文章 0 评论 0

我心依旧

文章 0 评论 0

晒暮凉

文章 0 评论 0

微信用户

文章 0 评论 0

DS

文章 0 评论 0

〆凄凉。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文