假设我有两个函数f,g它们都接受常规值并返回一个Either像这样的值:
g :: a -> Either x b
f :: b -> Either x c
Run Code Online (Sandbox Code Playgroud)
我如何将两者链接在一起以获得类似的东西f . g?
我想出的最佳解决方案是创建一个名为的辅助函数applyToRight,其工作方式如下
applyToRight :: (a -> Either x b) -> Either x a -> Either x b
applyToRight f x =
case x of
Left a -> Left a
Right b -> f b
Run Code Online (Sandbox Code Playgroud)
这样我就可以做
applyToRight f (g a)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我专门谈论Either,但我认为这个问题可以推广到所有应用函子。处理这个问题的最优雅的方法是什么?
haskell composition functor function-composition applicative
以下(工作)Haskell 程序输出随机拼写:
import System.Random
spells =
[ "Abracadabra!"
, "Hocus pocus!"
, "Simsalabim!"
]
main :: IO()
main = do
spell <- (spells !!) <$> randomRIO (0, length spells - 1)
putStrLn spell
Run Code Online (Sandbox Code Playgroud)
然而,这个变量spell是非常无用的。它存储从法术列表中选择的随机字符串,但随后会立即传递给putStrLn函数并且不再使用。我尝试将两个 IO 操作合并为一行,如下所示:
main = putStrLn <$> (spells !!) <$> randomRIO (0, length spells - 1)
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
• Couldn't match type ‘IO ()’ with ‘()’
Expected type: Int -> ()
Actual type: Int -> IO ()
• In the first argument of ‘(<$>)’, …Run Code Online (Sandbox Code Playgroud) 我正在阅读列表monad并遇到:
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
Run Code Online (Sandbox Code Playgroud)
它产生
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
Run Code Online (Sandbox Code Playgroud)
这是我理解的方式:
隐含括号是:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
Run Code Online (Sandbox Code Playgroud)
([1,2] >>= \n -> ['a','b']) 应该给 [('a',1),('b',1),('a',2),('b',2)]
因为
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs) -- this line
fail _ = []
Run Code Online (Sandbox Code Playgroud)
所以concat (map f xs)是concat (map (\n -> ['a','b']) [1,2])应当产生[('a',1),('b',1),('a',2),('b',2)]-实际输出的正好相反.
然后我不明白>>= (\ch -> return (n,ch))部分 - 我认为 …
我正在从“学习Haskell为伟大!”一书中学习单子。由Miran Lipovaca撰写。我试图理解单子的结合律。本质上,法律规定,当您使用拥有一元函数应用程序链时>>=,如何嵌套它们无关紧要。
以下代码使人们能够将type函数的结果传递给type a -> m b函数b -> m c:
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = (\x -> g x >>= f)
Run Code Online (Sandbox Code Playgroud)
但是,对于以下示例:
ghci> let f x = [x, -x]
ghci> let g x = [x*3, x*2]
ghci> let h = f <=< g
ghci> h 3
[9, -9, 6, -6]
Run Code Online (Sandbox Code Playgroud)
是f x和g x两个功能?看来它们是具有不同x值而不是函数的列表。该行在 …
在Haskell Monad中声明为
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
return = pure
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以将bind运算符重新声明为
(>>=) :: (a -> m b) -> m a -> m b
Run Code Online (Sandbox Code Playgroud)
?
第二个声明使将(>>=)type a -> m b的函数映射到type 的函数m a -> m b更清晰,而原始的声明却使它的含义更不清楚,是否正确?
声明的更改是否会使某些事情变为可能,甚至是不可能,或者只需要对使用monad进行一些更改(Haskell程序员似乎可以接受)?
谢谢。
haskell ×6
monads ×5
list ×2
applicative ×1
composition ×1
functor ×1
io-monad ×1
kleisli ×1
parentheses ×1
random ×1
syntax ×1