Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为条件分支组合这3类函数的通用方法是什么?_Haskell_Monads_Category Theory - Fatal编程技术网

Haskell 为条件分支组合这3类函数的通用方法是什么?

Haskell 为条件分支组合这3类函数的通用方法是什么?,haskell,monads,category-theory,Haskell,Monads,Category Theory,我有三个一元函数,我想把它们组合在一起,并有条件地在谓词上分支。我正在寻找可能有多种折衷的通用解决方案。箭头(ArrowChoice?)和单子看起来很有前途 人为的问题是: 我运行一项服务,跟踪许多客户的“个人号码”。如果他们是第一次登录,他们的号码设置为0。如果他们以前登录过,并且可能更改了他们的号码,那么将为他们获取该号码 所以这个程序的通用类型可以是program::Name->Int 我有3个函数,它们都可能具有查询持久数据存储(例如DB、State)的一元效应: 我希望能够将这些函数交

我有三个一元函数,我想把它们组合在一起,并有条件地在谓词上分支。我正在寻找可能有多种折衷的通用解决方案。箭头(ArrowChoice?)和单子看起来很有前途

人为的问题是:

我运行一项服务,跟踪许多客户的“个人号码”。如果他们是第一次登录,他们的号码设置为0。如果他们以前登录过,并且可能更改了他们的号码,那么将为他们获取该号码

所以这个程序的通用类型可以是
program::Name->Int

我有3个函数,它们都可能具有查询持久数据存储(例如DB、State)的一元效应:

我希望能够将这些函数交换给其他函数。例如,为
fetchFromDB
fetchFromStateMonad
交换
fetchFromStateMonad

“组合”它们的一种解决方案如下所示:

ex1 :: (a -> Bool) -> (a -> b) -> (a -> b) -> (a -> b)
-- or --
ex1 :: (Name -> Bool) -> (Name -> Int) -> (Name -> Int) -> (Name -> Int)
--     predicate         fetch            generate         result
这看起来有点像
ifM
,它使我更接近一个通用解决方案

但是当我调用
ex1“John”
时,它将进行一次数据库调用以确定谓词,另一次调用以
获取
John的号码。(当然,在这种狭隘的情况下,这很容易解决。我正在寻找一个更一般的)

我仍然不清楚如何通过
谓词
获取
执行单个数据库查询结果,但至少这种类型的签名允许这样做。现在有一个类型签名的问题,虽然它不太像合成,而是更特别


有没有办法概括这个问题?其中一些
组合
函数做了一切必要的事情,允许任意谓词和函数以我想要的方式连接起来

如果
new?
fetch
是两个独立的函数,则在任何情况下都必须进行两次查询。(一个用于检查名称是否在数据库中,另一个用于检查结果。)

然而,似乎
new?
是多余的
fetch
可以返回一个
值,以检索所需的编号或指示名称是新的。同时假设您的monad是
MonadIO
的一个实例,那么您的签名和函数如下

program :: MonadIO m => Name                  -- name to query
                     -> (Name -> m Maybe Int) -- fetch
                     -> (Name -> m Int)       -- generate
                     -> m Int                 -- number for name
program name fetch generate = fetch name >>= maybe (generate name) return

如果
new?
fetch
是两个独立的函数,则在任何情况下都必须进行两次查询。(一个用于检查名称是否在数据库中,另一个用于检查结果。)

然而,似乎
new?
是多余的
fetch
可以返回一个
值,以检索所需的编号或指示名称是新的。同时假设您的monad是
MonadIO
的一个实例,那么您的签名和函数如下

program :: MonadIO m => Name                  -- name to query
                     -> (Name -> m Maybe Int) -- fetch
                     -> (Name -> m Int)       -- generate
                     -> m Int                 -- number for name
program name fetch generate = fetch name >>= maybe (generate name) return

为什么是反对票?为什么是反对票?
program :: MonadIO m => Name                  -- name to query
                     -> (Name -> m Maybe Int) -- fetch
                     -> (Name -> m Int)       -- generate
                     -> m Int                 -- number for name
program name fetch generate = fetch name >>= maybe (generate name) return