我刚刚开始使用monad,我无法弄清楚为什么这两个表达式的评估方式不同:
ghci> [1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
ghci> return ([1,2],['a','b'])
([1,2],"ab")
Run Code Online (Sandbox Code Playgroud) 新手问题.假设我创建了一个简单的列表类型类,它接受两个字符串,如果它们是整数则添加它们各自的元素,如果它们是字符串则连接它们:
class NewList a where
addLists :: [a] -> [a] -> [a]
instance NewList Int where
addLists = addNumLists
addNumLists :: [Int] -> [Int] -> [Int]
addNumLists (x : xs) (y : ys) = x + y : addNumLists xs ys
addNumLists _ _ = []
instance NewList Char where
addLists x y = concat [x,y]
Run Code Online (Sandbox Code Playgroud)
这编译,但如果我addLists [1,2,3] [1,2,3]在GHCi中运行,我得到错误
<interactive>:278:11:
Ambiguous type variable `a0' in the constraints:
(Num a0) arising from the literal `1' at <interactive>:278:11
(NewList a0) …Run Code Online (Sandbox Code Playgroud) 我是Haskell的新手,所以如果你觉得这个问题很简单,请原谅我:
我如何让GHCi接受这种声明:let foo = fmap (*3) . fmap (+10)?
我尝试向foo(let foo :: [Int] -> [Int] =etc)添加一个类型声明,使functor类型显式,但编译器响应Illegal Signature.
谢谢!
编辑 - 显然有很多方法可以做到这一点.我选择了Tikhon的答案,因为他是第一个,而且相当直观.感谢大家!
当我不了解Haskell中的表达式如何工作时,我经常发现将其分解为更基本的形式会有所帮助.
使用以下定义
sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
Run Code Online (Sandbox Code Playgroud)
我改写sequenceA [(+3),(+2)] 3为
(\_ -> (:)) <*> (+3) <*> ((\_ -> (:)) <*> (+2) <*> (\_-> [])) $ 3
Run Code Online (Sandbox Code Playgroud)
然后把它变成(请原谅格式;我不确定分割线的惯例是什么)
(\d ->(\c->(\b -> (\a -> (\_ -> (:)) a (+3) a) …
来自Haskell 的功能性思考,第 67 页:
[...] list comprehensions are translated into equivalent definitions in
terms of map and concat. The translation rules are:
[e | True] = [e]
[e | q] = [e | q, True]
[e | b, Q] = if b then [e | Q] else []
[e | p <- xs, Q] = let ok p = [e | Q]
ok _ = []
in concat (map ok xs)
Run Code Online (Sandbox Code Playgroud)
作者没有在任何地方定义 e、q、Q 或 b。我认为第一个意思是“表达”,但我以前从未见过其他人。有人可以启发我吗?