在哈斯克尔工作,发现奇怪的行为,将其剥离为裸骨
这个作品
a :: Bool
a = case True of
True -> True
False -> False
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试
b :: IO Bool
b = do
let b' = case True of
True -> True
False -> False
return b'
Run Code Online (Sandbox Code Playgroud)
我明白了
ghci>:l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:16:14: parse error on input ‘->’
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
所以我试试
c :: IO Bool
c = do
let c' = case True of
True -> True
False -> False …Run Code Online (Sandbox Code Playgroud) 我正在学习哈斯克尔。
\n我正在尝试查找列表中as与列表元素相加的元素bs,并将元素作为元组返回:
findSum2 :: [Int] -> [Int] -> [(Int,Int,Int)]\nfindSum2 as bs = [(a, a', b) | a <- as, a' <- as, b <- bs, a + a' == b]\nRun Code Online (Sandbox Code Playgroud)\n该代码有效。但为了学习 Haskell,我尝试将其重写为do-notation:
findSum2 :: [Int] -> [Int] -> [(Int,Int,Int)]\nfindSum2 as bs = do\n a <- as\n a' <- as \n b <- bs\n if a + a' == b then return (a, a', b) \n else return ()\nRun Code Online (Sandbox Code Playgroud)\n然后类型检查员向我抱怨: …
我最近在使用threepenny-gui时遇到了一个错误
,它通过将符号中的模式匹配的代码更改为<-与let符号的模式匹配来解决.
在这两种模式匹配形式之间进行转换时,我是否应该期望改变行为?
具体如下代码:
在IO monad中:
Just events <- Map.lookup elid <$> readMVar sElementEvents
Run Code Online (Sandbox Code Playgroud)
改为:
mevents <- Map.lookup elid <$> readMVar sElementEvents
let Just events = mevents
Run Code Online (Sandbox Code Playgroud)
这是一个提交的链接,为我解决了问题:https: //github.com/Davorak/threepenny-gui/commit/fbf6cbe25875fafdc64f7a111ddebf485b45143b
其他平台细节:os:10.8.5 ghc:7.6.3
编辑:添加了这个发生在IO monad的事实
问题在底部以粗体显示。
LYAH 给出了这个使用monaddo符号的例子Writer
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["number " ++ show x])
multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
return (x*y)
Run Code Online (Sandbox Code Playgroud)
定义可以在没有do符号的情况下重写:
multWithLog = logNumber 3 >>= (\x ->
logNumber 5 >>= (\y ->
return (x*y)))
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好。
之后,书中介绍了tell,并编辑了这样的定义multWithLog:
multWithLog = do
a <- logNumber 3
b <- logNumber 5
tell ["something"]
return …Run Code Online (Sandbox Code Playgroud) 为什么允许使用此功能:
-- function 1
myfunc :: String
myfunc = do
x <- (return True)
show x
Run Code Online (Sandbox Code Playgroud)
这不是:
-- function 2
myfunc :: String
myfunc = do
x <- getLine
show x
Run Code Online (Sandbox Code Playgroud)
编译错误:
Couldn't match type `[]' with `IO'
Expected type: IO Char
Actual type: String
Run Code Online (Sandbox Code Playgroud)
我明白为什么功能 2 不应该工作,但为什么功能 1 工作呢?
为什么这会起作用:
-- function 3
myfunc = do
x <- getLine
return (show x)
Run Code Online (Sandbox Code Playgroud)
我知道它IO String然后返回,但是为什么函数 1 也没有被迫这样做?
该文件指出,“运行块地方不能是独立的语句最简单的方法是通过编写do之前”,并提供了下面的例子:
# This dies half of the time
do { say "Heads I win, tails I die."; Bool.pick } or die; say "I win.";
Run Code Online (Sandbox Code Playgroud)
但是,do似乎不会导致所有块都运行。特别是,它似乎没有运行带有签名的块:
do -> $a = 42 { say "ran with $a"; 0 } or die; say 'done'; # OUTPUT: «done»
Run Code Online (Sandbox Code Playgroud)
那么将do块视为有时会导致它运行的表达式会更好吗?还是乐堂在这里的行为不正确?还是我的理解不正确?
我想在Haskell中依次组合两个monad动作,丢弃第二个动作产生的任何值,并将参数传递给两个动作.目前我正在使用这样的do-block:
ask = do
result <- getLine
putStrLn result
return result
Run Code Online (Sandbox Code Playgroud)
我本来希望写一点免费和整洁,所以我尝试了这个:
ask' = getLine <* putStrLn
Run Code Online (Sandbox Code Playgroud)
但是,这甚至不进行类型检查,问题是<*不会将第一个动作的结果传递给第二个动作.我希望将操作链接起来>>=,但不会更改结果.类型应该是(a -> m b) -> (a -> m c) -> (a -> m b),但Hoogle没有产生合适的结果.实现此功能组合的操作员是什么?
对于简单的函数组合,是否有"do notation"语法糖?
(即(.) :: (b -> c) -> (a -> b) -> a -> c)
我希望能够存储一些成分的结果供以后使用(同时仍然继续链.
如果可能的话,我宁愿不使用RebindableSyntax扩展.
我正在寻找这样的东西:
composed :: [String] -> [String]
composed = do
fmap (++ "!!!")
maxLength <- maximum . fmap length
filter ((== maxLength) . length)
composed ["alice", "bob", "david"]
-- outputs: ["alice!!!", "david!!!"]
Run Code Online (Sandbox Code Playgroud)
我不确定这样的事情是否可能,因为早期函数的结果基本上必须通过"通过"maxLength的绑定,但我愿意听到任何其他类似的表达选项.基本上我需要收集信息,因为我通过合成以便以后使用它.
也许我可以用状态monad做这样的事情?
谢谢你的帮助!
编辑
这种事情有点起作用:
split :: (a -> b) -> (b -> a -> c) -> a -> c
split ab bac a = bac (ab a) a
composed …Run Code Online (Sandbox Code Playgroud) 我想在do块中实现以下目标:
do
if condition then
n0 <- expr0
else
n0 <- expr0'
n1 <- expr1
n2 <- expr2
return T n0 n1 n2
Run Code Online (Sandbox Code Playgroud)
但是Haskell会给出一个编译错误,除非我这样做:
do
if condition then
n0 <- expr0
n1 <- expr1
n2 <- expr2
return T n0 n1 n2
else
n0 <- expr0'
n1 <- expr1
n2 <- expr2
return T n0 n1 n2
Run Code Online (Sandbox Code Playgroud)
它看起来很冗长,尤其是当有许多共享的绑定表达式时。如何使其更简洁?
实际上,我正在尝试执行以下操作:
do
if isJust maybeVar then
n0 <- f (fromJust maybeVar)
n1 <- expr1
n2 <- expr2
return (T (Just n0) n1 …Run Code Online (Sandbox Code Playgroud) OCaml 是否与 Haskell 的 Do Notation 等效?
另一种说法 - 有没有一种简单的方法可以更轻松地处理嵌套的 monadic 操作......因为这很烦人:
open Batteries
open BatResult.Infix
let () =
let out =
(Ok("one")) >>=
(fun a ->
let b = Ok("two") in
b >>= (fun c ->
print_endline(a);
print_endline(c);
Ok(c)
)) in
ignore(out)
Run Code Online (Sandbox Code Playgroud) do-notation ×10
haskell ×8
monads ×5
bind ×1
composition ×1
expression ×1
indentation ×1
list ×1
ocaml ×1
pointfree ×1
raku ×1
rakudo ×1
refactoring ×1
rewriting ×1
writer-monad ×1