haskell - 如何在单子(monad)中使用 Kleisli 箭头?

标签 haskell monads arrows kleisli

在 Haskell Control.Arrow文档它谈到了 Kleisli 箭头与单子(monad)的关系,但对我来说如何使用它并不明显。我有一个我认为适合箭头的功能,除了它涉及 IO monad,所以我认为 Kleisli 箭头可能会有所帮助。

采用以下函数,它返回目录的原始文件名和修改后的文件名对。

import System.Directory
import System.FilePath

datedFiles target = do
    fns <- getDirectoryContents target
    tms <- mapM (fmap show . getModificationTime) fns
    return $ 
        zip fns $ 
        zipWith replaceBaseName fns $ 
        zipWith (++) (map takeBaseName fns) tms

如果我必须把它画出来,它会是这样的:

enter image description here

我认为它可以从使用 Kleisli 箭头中受益,但我不知道如何。任何人都可以提供指导吗?

最佳答案

单子(monad)是 Functor s 从 Hask(Haskell 类型和函数的范畴)到 Hask——一个内仿函数。这意味着 Hask 中的一些箭头看起来像 a -> m b对于一些 Monad m .对于特定的单子(monad) m ,Hask 的子类别,其中箭头看起来像 a -> m bm 的 Kleisli 类别.

我们知道这是一个类别,因为有一个标识箭头 return :: a -> m a和作文(>>>) :: (a -> m b) -> (b -> m c) -> (a -> m c)定义为

(f >>> g) a = join (g <$> f a)

这就是为什么我们需要将其设为 Monad ---我们同时使用 returnjoin .

在 Haskell 中,我们通常不能只使用子类别,而是使用新类型。
import Prelude hiding ((.), id)
import Control.Category

newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }

instance Monad m => Category (Kleisli m) where
  id                    = Kleisli return
  Kleisli g . Kleisli f = Kleisli (join . fmap g . f)

然后我们可以升级Monad m => a -> m b类型的功能至Kleisli m a b s,类别中的箭头,并用 (.) 组合它们
arr :: Kleisli IO FilePath [String]
arr = Kleisli (mapM $ fmap show . getModificationTime) . Kleisli getDirectoryContents

不过,通常这在语法上有点嘈杂。新类型只有在使用 Category 时才有值(value)。要重载的类型类 id(.) .相反,您更有可能看到 return(>=>)相当于
return a = runKleisli (id a)
f >=> g  = runKleisli $ Kleisli g . Kleisli f

关于haskell - 如何在单子(monad)中使用 Kleisli 箭头?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20165554/

相关文章:

r - Plotly:如何使用 add_annotations 设置箭头的样式和颜色?

haskell - 我可以映射一对没有箭头的第一个元素吗?

parsing - Haskell/Parsec : How do you use the functions in Text. Parsec.Indent?

list - 如何在 haskell 中进行有状态列表操作

haskell - 为什么我找不到 NotQuiteCofree not-quite-comonad 的任何违法行为?

scala - flatMap 忽略结果

opengl - 如何使用 opengl 在 Haskell 中绘制圆圈

haskell - 努力在servant中连接一对类型类约束单子(monad)

rust - 有没有办法让 Rust 相信特定的关联类型与具体类型相同?

haskell - 如何处理在组合下发生变化的类型?