应用功能单子
我知道我可以使用函数单子来实现类似下面的一个结构(在这里我重复使用多次调用的参数不明确引用它)之前执行转换到输入:应用功能单子
compute_v0 :: String -> String
compute_v0 = do
x <- length -- (using the argument implicitly here)
top <- head -- (and here)
return (replicate x top)
对上述函数的结果:compute "1234"
将"1111"
我的问题是:我将如何执行做块之前应用转换到“隐藏”的说法(想象一下,我想追加“ABCD “到列表中)。
我的第一个解决方案:
compute_v1 :: String -> String
compute_v1 = compute_v1' . (++ "abcd")
compute_v1' ::String -> String
compute_v1' = do
x <- length
top <- head
return (replicate x top)
为compute "1234"
结果现在是"11111111"
。这实际上完成了这项工作,但我宁愿将它全部定义在一个简洁的代码块中。
我能得到的最接近实际包括同时仍保持与代码(V0)的风格改造这一项:
compute_v2 :: String -> String
compute_v2 = (++ "abcd") >>= \r -> do
let x = length r
let top = head r
return $ replicate x top
但我还是必须包括一个拉姆达,使用了大量的let绑定的并明确引用lambda参数。有更好的方法来实现这样的结构吗?
由于所有Monad
情况下,也有Functor
实例和Functor
功能实例有fmap = (.)
,你可以有
compute :: String -> String
compute = flip fmap (++ "abcd") $ do
x <- length
top <- head
return $ replicate x top
有些软件包(如microlens
和lens
)定义(<&>) = flip fmap
,让你写
compute :: String -> String
compute = (++ "abcd") <&> do
x <- length
top <- head
return $ replicate x top
(->)
也有一个Category
实例,其中giv es我们(>>>) = flip (.)
。这可能会稍微更清晰,视觉:
compute :: String -> String
compute = (++ "abcd") >>> do
x <- length
top <- head
return $ replicate x top
你可以做这样的事情:
compute_v2 :: String -> String
compute_v2 = do
x <- length
top <- head
return $ replicate x top
<$> (++ "abcd")
据我所知,有问题的单子被称为读者单子,并且它也是一个Functor
。
*Q46393211> compute_v2 "1234"
"11111111"
*Q46393211> compute_v2 "71"
"777777"
@chi GHCi中加载的模块中的代码没有解析错误。我还没有尝试'真正'编译它... –
我喜欢这些“简单”的Haskell问题和答案,他们总是让我的脑袋迅速旋转。我目前对此有所了解:''是'fmap'的中缀运算符(查找[here](https://stackoverflow.com/questions/37286376/what-does-mean-in-haskell))。左边的任何东西都是一个函数'a-> b',右边是'f a'。所以这是一个函数?对于'do'块本身,这是'List' monad,因为字符串是字符列表? –
@StefanHanke不,它一直是函数monad(和函数函子)。 “(++“abcd”)'。如果我有这样的事情,我会亲自把这些包裹放在明确的位置。 –
MonadReader
class有这种情况的方法local
和(->) r
是一个实例,因此
import Control.Monad.Reader (local)
compute_v3 ::String -> String
compute_v3 = local (++ "abcd") $ do
x <- length
top <- head
return (replicate x top)
应该工作(不能在此刻测试)。
'compute_v1 = liftA2重复长度头。 (++“abcd”)' – 4castle
'compute_v1 =(复制长度头)。 (++“abcd”)' – Redu