in this post, we will going to examine the list a monad, first let's see what is the definition of the list monad, here is the definition of the
instance Monad [] where return x = [x] xs >>= f = concat (map f xs) fail _ = []
since list are also monad, and given the definition of the >>=, here is what you can get from the list monad.
ghci> [3,4,5] >>= \x -> [x,-x] [3,-3,4,-4,5,-5]
the [] is now the Nothing, as can be told by this:
ghci> [] >>= \x -> ["bad","mad","rad"] [] ghci> [1,2,3] >>= \x -> [] []
we can chain the [] as we do the Maybe type.
ghci> [1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch) [(1,'a'),(1,'b'),(2,'a'),(2,'b')]
this is like the list comprehension, if we write the code in the do notation.
listOfTuples :: [(Int,Char)] listOfTuples = do n <- [1,2] ch <- ['a','b'] return (n,ch)
and we can as well use the special syntax which has a name called "list comprehension".
ghci> [ (n,ch) | n <- [1,2], ch <- ['a','b'] ] [(1,'a'),(1,'b'),(2,'a'),(2,'b')]
but the list comprehension allow us to filter the output ,an example is as follow.
ghci> [ x | x <- [1..50], '7' `elem` show x ] [7,17,27,37,47]
how does that translate to the list monad? we will need to see the guard method and the MonadPlus type class, first let's see the MonadPlus definition.
class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a
Monad Plus can also act as monoid. (not mean that it is a monoid?)
which is shown in the following MonadPlus [] instance definition.
instance MonadPlus [] where mzero = [] mplus = (++)
so, how is the guard method implememented?
guard :: (MonadPlus m) => Bool -> m () guard True = return () guard False = mzero
so we can have this:
ghci> guard (5 > 2) :: Maybe () Just () ghci> guard (1 > 2) :: Maybe () Nothing ghci> guard (5 > 2) :: [()] [()] ghci> guard (1 > 2) :: [()] []
so, we can implement filter with monad something like this:
ghci> [1..50] >>= (\x -> guard ('7' `elem` show x) >> return x) [7,17,27,37,47]
so combined with the >> method of the Monad, here is what it looks like:
ghci> guard (5 > 2) >> return "cool" :: [String] ["cool"] ghci> guard (1 > 2) >> return "cool" :: [String] []
Here's is the previous example rewritten in do notation.
sevensOnly :: [Int] sevensOnly = do x <- [1..50] guard ('7' `elem` show x) return x
remember we need to have the ending "return x". otherwise we will get the empty tuple.
let's me try to explain how that works? because guard work on bool and return a monoid, and List are monoid, so [1..50] are decomposed into [1] :[2] :[3] : [4],..,[50]. and each will be applied with the guard(),and that will return return(), or mzero based on the bool value.
As with other typeclass, there are some laws that guide over the monad typeclass.
- left identity
return x>>=f is the same as the f x
an example is as
ghci> return 3 >>= (\x -> Just (x+100000)) Just 100003 ghci> (\x -> Just (x+100000)) 3 Just 100003
- right identity
the second law states that if we have a monadic value and we can >>= to feed it to return , the results is our original monadic value, formally:
m >>= return is no different than just m
example is as follow.
we know that the list .>= is like this :
xs >>= f = concat (map f xs)
So when we feed [1,2,3,4] to return, first return gets mapped over [1,2,3,4], resulting in [[1],[2],[3],[4]]and then this gets concatenated and we have our original list.
Left identity and right identity are basically laws that describe how return should behave. It's an important function for making normal values into monadic ones and it wouldn't be good if the monadic value that it produced did a lot of other stuff.
- Associativity
The final monad law says that when we have a chain of monadic function applications with >>=, it shouldn't matter how they're nested. Formally written:
Doing (m >>= f) >>= g is just like doing m >>= (\x -> f x >>= g)
we can make a chain of calll like the following.
ghci> return (0,0) >>= landRight 2 >>= landLeft 2 >>= landRight 2 Just (2,4)
and if we parenthesize this, we 'd get .
ghci> ((return (0,0) >>= landRight 2) >>= landLeft 2) >>= landRight 2 Just (2,4)
but we can also write the routine like this:
return (0,0) >>= (\x -> landRight 2 x >>= (\y -> landLeft 2 y >>= (\z -> landRight 2 z)))
so, look at this rule like this:
it doesn't matter how you nest feeding values to monadic functions, what matters is their meaning. Here's another way to look at this law
consider the two function, f, and g, composing the two is like this:
(.) :: (b -> c) -> (a -> b) -> (a -> c) f . g = (\x -> f (g x))
but the value we are dealing with for Monadic value ? we cannot chain them together, but fortunately >>= to make that happen. so by using >>= , we can compose two monadic functions.
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c) f <=< g = (\x -> g x >>= f)
相关推荐
常见的Monad有 IO、Maybe 和 List。Monad 提供了一种顺序组合操作的机制,使得纯函数式编程中也能处理副作用。在“haskell-training-master”中,你会逐步理解Monad的概念及其在实际编程中的应用。 **数据类型和...
6. **Monads**:Monad是Haskell中的一个关键概念,用于处理副作用、状态和异常等复杂情况。它们通过组合操作实现了控制流的抽象,是函数式编程中处理副作用的一种优雅方式。 在“haskell-book-master”中,可能包含...
练习涵盖State、IO、Maybe和List等常见Monad的使用,帮助你掌握Monad的基本操作和组合。 6. **Functors和Applicative Functors**:这两个概念是理解Monads的基础。练习会涉及如何定义和使用Functor及Applicative ...
3. Monads:理解monads的概念,如IO、Maybe、List等monad,以及如何使用do notation进行monadic操作。 4. Lazy Evaluation:了解惰性求值的工作原理及其对性能和内存管理的影响。 5. 类型系统:深入理解Haskell的强...
7. **Monads**:如果项目涉及到IO操作,可能会使用到Monad,理解何为Monad,以及如何使用Maybe、List和IO Monad。 8. **数据结构**:使用Haskell内置的数据结构,如列表、元组、树等,以及如何创建自定义数据类型。...
用monad构建列表 其中包含属于博客帖子的代码,基准和分析,其中包含了来自想法。 和 。 图表 该图省略了一些效率较低的变体,从而使细节更清晰可见。 基准结果 该表忽略了具有二次运行时间的那些变体,因为我不想在...
#### 七、列表Monad(The List Monad) 本章重点介绍了列表Monad的应用场景和实现方式。列表Monad常用于表示多个可能的结果或分支。 ##### 示例: - **嵌套do块循环**(VIIa Nested do Block Loop):通过嵌套do块...
Monad-Skeleton 库通常包含一系列常见的 Monad 实现,如 Maybe、List、IO、State、Writer、Reader 和 Error 等。每个 Monad 都有自己的行为特性,例如: 1. **Maybe Monad**:处理可能的空值,避免空指针异常。当...
Monads是Haskell中用于处理副作用、组合序列化操作和管理状态的强大工具。第十二章和第十三章详细讲解了Maybe Monad、Monad类型类、do表示法以及List Monad等高级特性。Monad的介绍会让读者对Haskell的高级特性有更...
在哈斯克尔的学习过程中,你可能会遇到诸如类型推导、monads(如 IO、Maybe 和 List Monad)等高级主题。Monads 是一种抽象概念,用来处理副作用和控制流,是哈斯克尔中解决这些问题的关键工具。理解 monads 对于...
了解了Monads的基础知识之后,可以通过阅读更多关于Haskell和函数式编程的资源来深化对Monads的理解。以下是一些推荐的学习资源: - **《Real World Haskell》**: 一本详尽介绍Haskell编程的书籍,包括Monads在内的...
常见Monad如Maybe(处理可能的null)、IO(处理I/O操作)和List(处理序列)等。Monad的概念在理解Haskell的高级编程技巧中至关重要。 7. **类型推导** Haskell的类型推导系统能够自动确定大多数表达式的类型,...
5. **Monads**:作为Haskell中的一个核心概念,Monad是控制流程和副作用管理的关键工具。书中会介绍常见Monad如IO、Maybe、List和State等。 6. **并行与并发**:Haskell的纯函数性质使其天生适合并行和并发编程,书...
8. **Monads(Monad)** - **Monad**:是一种抽象概念,用于处理副作用和控制流,如 IO 操作。 - **do 语句**:使用 `do` 语句编写 monadic 代码,使其更接近命令式编程风格。 - **常用 Monad**:包括 `Maybe`...
6. **Monads**:Monad是Haskell中处理副作用的一种抽象方式,常用于I/O操作。`huffman.hs`可能是关于Huffman编码的实现,其中可能运用了State或IO Monad来处理数据压缩。 通过分析这些源代码文件,我们可以深入学习...
4. Monads:Monad是一种抽象概念,用于处理副作用。理解Monads是Haskell高级编程的关键。 5. List comprehensions:类似于Python的列表推导,Haskell提供了一种简洁的构造列表的方式。 6. Pattern matching:通过...
- Monad是Haskell处理副作用和控制流的一种抽象方式,常用于IO操作、状态管理等。 - `Maybe`和`Either`是基本的Monad实例,它们分别用于处理可能的空值和错误情况。 6. 高阶函数与模式匹配 - 高阶函数如`map`、`...
- **Monad是一种抽象,用来处理副作用**:在Haskell中,一切皆为函数,Monads提供了一种封装副作用的方式。 - **IO Monad**:用于处理输入/输出操作,如读写文件、网络通信等。 - **Maybe Monad**:处理可能的...