到目前为止,我遇到的每个monad(可以表示为数据类型)都有相应的monad变换器,或者可以有一个.有这样一个不能有一个单子吗?或者所有monad都有相应的变压器?
通过对应于monad的变换器t,m我的意思t Identity是同构的m.当然,它满足monad变压器法则,并且t n是任何monad的monad n.
我希望看到每个monad都有一个证明(理想情况下是建设性的证明),或者没有一个证明(带证明)的特定monad的例子.我对更多面向Haskell的答案以及(类别)理论答案感兴趣.
作为后续问题,是有一个单子m是有两个不同的变压器t1和t2?也就是说,t1 Identity同构t2 Identity和m,但有一个单子n这样t1 n是不是同构t2 n.
(IO并且ST有一个特殊的语义,所以我不在这里考虑它们,让我们完全忽略它们.让我们只关注可以使用数据类型构造的"纯"monad.)
Monads可以做许多惊人的,疯狂的事情.他们可以创建具有值叠加的变量.它们可以允许您在计算之前访问未来的数据.它们可以让您编写破坏性更新,但不是真的.然后延续monad让你打破人们的思想!通常是你自己的.;-)
但这是一个挑战:你能制作一个可以暂停的单子吗?
data Pause s x instance Monad (Pause s) mutate :: (s -> s) -> Pause s () yield :: Pause s () step :: s -> Pause s () -> (s, Maybe (Pause s ()))
该Pause单子是一种状态的单子(因此mutate,具有明显的语义).通常情况下,像这样的monad具有某种"运行"功能,它运行计算并将您送回最终状态.但Pause它是不同的:它提供了一个step函数,它运行计算直到它调用魔法yield函数.这里计算暂停,返回给调用者足够的信息以便稍后恢复计算.
额外的awesomness:允许调用者修改step调用之间的状态.(例如,上面的类型签名应该允许这样做.)
使用案例:编写执行复杂操作的代码通常很容易,但是要将其转换为也在其操作中输出中间状态的总PITA .如果您希望用户能够在执行过程中途改变某些内容,那么事情变得非常复杂.
实施思路:
显然它可以用线程,锁和IO.但我们能做得更好吗?;-)
继续monad疯狂的东西?
也许是某种编写器monad,yield只记录当前状态,然后我们可以step通过迭代日志中的状态来"假装" 它.(显然这排除了改变步骤之间的状态,因为我们现在并没有真正"暂停"任何东西.)
让我困惑的一件事是,是否可以使用IORef.在决定是否使用IORef执行任务时是否应遵循任何指导原则?什么时候是使用州立大学的好时机而不是IORef?
Monad通常用return和来解释bind.不过,我猜想你也可以实现bind在以下方面join(和fmap?)
在缺乏一流功能的编程语言中,使用起来bind非常难以捉摸.join另一方面,看起来很容易.
但是,我并不完全确定我理解它是如何join运作的.显然,它有[Haskell]类型
join :: Monad m => m (m x) -> m x
对于monad列表,这显然很简单concat.但是对于一般的monad来说,这种方法在操作上实际上做了什么?我看到它对类型签名的作用,但我试图弄清楚我是如何在Java或类似的东西中写出这样的东西.
(实际上,这很容易:我不会.因为仿制药已经坏了.;-)但原则问题仍然存在......)
哎呀.看起来之前有人问过:
可能有人勾画出使用普通的单子一些实现return,fmap和join?(即,根本没有提到>>=.)我想也许这可能有助于它沉入我愚蠢的大脑......
似乎已经达成共识,你应该使用Parsec作为应用而不是monad.应用解析比monadic解析有什么好处?
monadic解析了吗?
有什么区别map和flatMap功能Iterable?
上帝我讨厌"代码味"这个词,但我想不出更准确的东西.
我正在业余时间为Whitespace设计一个高级语言和编译器,以了解编译器构造,语言设计和函数编程(编译器是用Haskell编写的).
在编译器的代码生成阶段,我必须在遍历语法树时保持"状态" - 数据.例如,在编译流控制语句时,我需要为要跳转到的标签生成唯一的名称(从传入,更新和返回的计数器生成的标签,并且绝不能再次使用计数器的旧值).另一个例子是当我在语法树中遇到内联字符串文字时,它们需要永久转换为堆变量(在空白中,字符串最好存储在堆上).我目前正在处理状态monad中的整个代码生成模块来处理这个问题.
我被告知编写编译器是一个非常适合功能范例的问题,但我发现我的设计方式与我在C中设计它的方式大致相同(你真的可以用任何语言编写C语言 - 甚至Haskell w/state monads).
我想学习如何在Haskell中思考(而不是在函数范式中) - 而不是在C中使用Haskell语法.我真的应该尝试消除/最小化状态monad的使用,还是一个合法的功能"设计模式"?
我有一个字符串列表,并试过这个:
ls = [ "banana", "mango", "orange" ]
main = do
map PutStrLn list_of_strings
Run Code Online (Sandbox Code Playgroud)
这不起作用,我不明白为什么.
ghc print-list.hs
print-list.hs:3:0:
Couldn't match expected type `IO t' against inferred type `[IO ()]'
In the expression: main
When checking the type of the function `main'
Run Code Online (Sandbox Code Playgroud)
任何提示?我想它与map返回列表而不是值有关,但我没有找到一种简单的方法来解决这个问题.
现在,我知道打印字符串列表的唯一方法是编写一个函数来迭代列表,打印每个元素(如果列表是[a]则打印,但如果是(a:b)则打印和递归).但是,这将是很多简单的只使用地图...
谢谢!
我试图定义一个新的monad,我得到一个奇怪的错误
newmonad.hs
newtype Wrapped a = Wrap {unwrap :: a}
instance Monad Wrapped where
(>>=) (Wrap x) f = f x
return x = Wrap x
main = do
putStrLn "yay"
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.1
$ ghc newmonad.hs
[1 of 1] Compiling Main ( newmonad.hs, newmonad.o )
newmonad.hs:2:10:
No instance for (Applicative Wrapped)
arising from the superclasses of an instance declaration
In the instance declaration for ‘Monad Wrapped’
为什么我需要定义一个实例Applicative?
在我的业务领域 - 金融机构的后台IT - 软件组件通常进行全局配置,记录其进度,进行某种错误处理/计算短路是很常见的...可以通过Haskell中的Reader-,Writer-,Maybe-monads等很好地建模,并与monad变换器一起组合.
但似乎存在一些缺点:monad变换器背后的概念非常棘手且难以理解,monad变换器导致非常复杂的类型签名,并且它们会造成一些性能损失.
所以我想知道:monad变形金刚在处理上述常见任务时是最佳做法吗?
monads ×10
haskell ×9
applicative ×1
coding-style ×1
coroutine ×1
free-monad ×1
io ×1
ioref ×1
parsec ×1
scala ×1
state ×1
state-monad ×1