我在研究功能反应式编程时发现了这一说法,来自Hai Liu和Paul Hudak的"用箭头堵塞空间泄漏"(第5页):
Run Code Online (Sandbox Code Playgroud)Suppose we wish to de?ne a function that repeats its argument inde?nitely: repeat x = x : repeat x or, in lambdas: repeat = ?x ? x : repeat x This requires O(n) space. But we can achieve O(1) space by writing instead: repeat = ?x ? let xs = x : xs in xs
这里的差异似乎很小,但它极大地促进了空间效率.为什么以及如何发生?我做的最好的猜测是手工评估它们:
r = \x -> x: r x
r 3
-> 3: r 3
-> 3: 3: 3: …Run Code Online (Sandbox Code Playgroud) 我在Monad.Reader#13中阅读了Brent Yorgey的"The Typeclassopedia" ,发现"Functor hierachy "与图1所示的"Category hierachy "是相互依赖的.
并且根据作者的说法ArrowApply == Monad,特别是前一个只是一个可以在何时使用的类型类实例
"我们希望能够从中间结果计算箭头,并使用此计算箭头继续计算.这是ArrowApply给予我们的力量."
但是我们如何把这些东西放在一起呢?我的意思是Monad和Arrow都有一些流控制功能(喜欢if和elsevs. ArrowChoice,或者forM相比ArrowLoop),而Monad((***),(|||)或first)中的某些功能似乎"缺失" .所有这些似乎都需要在使用Monad或Arrow系统来构建我们的副作用计算流程之间做出选择,并且会在另一个系统中丢失一些功能.
在我对Haskell的第一印象中,它是一种语言可以非常好地处理"执行然后结果"的事情.但我找不到如何实现游戏或HTTP/FTP/TCPSocket服务器等"事件驱动"的东西.
在我阅读了一些关于FRP的论文后,这个问题得到了解答,包括Yampa和由它创建的FPS游戏(Frag).看起来FRP是一个很好的模型来实现像3D游戏这样的"重型"事件驱动的东西,但是如何轻松的事件驱动的应用程序如HTTP服务器或普通的桌面GUI程序呢?如果我使用FRP来实现所有这些东西会出现什么缺点?
这些"简单"的线条出了点问题......
action = do
isdir <- doesDirectoryExist path -- check if directory exists.
if(not isdir)
then do handleWrong
doOtherActions -- compiling ERROR here.
Run Code Online (Sandbox Code Playgroud)
GHCi会投诉标识符,或者在我添加后不执行最后一行操作else do.
我认为异常处理可能有效,但是在这种常见的"检查并做某事"声明中是否有必要?
谢谢.
我设计了一个计算列表均值的函数.虽然它工作正常,但我认为它可能不是最好的解决方案,因为它需要两个功能而不是一个.只用一个递归函数就可以完成这项工作吗?
calcMeanList (x:xs) = doCalcMeanList (x:xs) 0 0
doCalcMeanList (x:xs) sum length = doCalcMeanList xs (sum+x) (length+1)
doCalcMeanList [] sum length = sum/length
Run Code Online (Sandbox Code Playgroud) 我有一个shuffle功能Array:
shuffle:: forall e. Array -> Eff (random :: RANDOM | e) Array
Run Code Online (Sandbox Code Playgroud)
它将 monad 中的数组打乱Control.Monad.Eff.Random并返回包装后的数组。我想测试数组是否被打乱,想比较结果是否不同,所以我编写了 QuickCheck 代码,如下所示:
quickCheck \arr -> isShuffled (shuffle arr)
Run Code Online (Sandbox Code Playgroud)
但是,我不确定如何编写isShuffled以匹配类型定义。自从:
没有像fromJustin那样的解包函数Maybe,因此它必须接受Random Array并返回Random Boolean,而我将检查代码放在 Monadic 表达式中。
因此,结果isShuffled不会很简单Boolean,而是像m Boolean
forTestable中没有合适的,所以我可能需要为其创建一个实例,而 QuickCheck 中的注释提到:purescript-quickcheckm Boolean
A testable property is a function of zero or more Arbitrary arguments, returning a Boolean or Result.(代码 …
我在"真实世界Haskell"一书中找到了这样的代码,p68
data Tree a = Node a (Tree a) (Tree a)
| Empty
deriving (Show)
nodeAreSame (Node a _ _) (Node b _ _)
| a == b = Just a
nodeAreSame _ _ = Nothing
Run Code Online (Sandbox Code Playgroud)
我的问题是:Just数据构造函数做了什么工作?当我删除它时,我会收到类似的错误消息
(in ghci)
......
<Main *> nodeAreSame (Node 3 Empty Empty) (Node 3 Empty Empty))
<interactive>:1:16:
No instance for (Num (Maybe a))
......
Run Code Online (Sandbox Code Playgroud)
但是当我尝试比较"Just"和"No Just"版本之间的类型差异时:
nodeAreSameJust :: (Eq t) => Tree t -> Tree t -> Maybe t
nodeAreSameNoJust :: (Eq a) …Run Code Online (Sandbox Code Playgroud) 根据介绍ReaderT,我只能找到:
ReaderT Env IO String
Run Code Online (Sandbox Code Playgroud)
这意味着
...is a computation which involves reading values from some environment
of type Env (the semantics of Reader, the base monad) and performing some
IO in order to give a value of type String.
Run Code Online (Sandbox Code Playgroud)
因此执行的顺序将成为
1. ( Already has ) some environment values -- ReaderT Env
2. Do `IO` accroding to these pre-existing values -- IO a
3. Use the `IO a` values to do more computations -- IO b...z
Run Code Online (Sandbox Code Playgroud)
这将要求我们的程序有一些预先存在的值作为环境,但我认为大多数程序需要加载这些环境值.如数据库URL,调试切换器或其他任何东西. …
我有两个免费的monad用于不同的上下文中的不同操作.但是,如果特定操作在上下文中,则one(major)DSL需要包含另一个(action):
import Control.Monad.Free
data ActionFunctor next = Wait Timeout next
| Read URI next
instance Functor ActionFunctor where
fmap f (Wait timeout next) = Wait timeout (f next)
fmap f (Read uri next) = Read uri (f next)
type Action = Free ActionFunctor
data MajorFunctor next = Log LogText next
| Act Action next
| Send Message
instance Functor MajorFunctor where
fmap f (Log text next) = Log text (f next)
fmap f (Act action next) …Run Code Online (Sandbox Code Playgroud) 我正在阅读有关Cassandra维修的文件,它说
比较从Merkle树的顶部节点开始。如果未检测到差异,则处理进行到左子节点,然后进行比较,然后比较右子节点。
但是,默克尔树的非叶节点表示:
树中较高的每个父节点都是其各自子节点的哈希。由于Merkle树中的较高节点表示数据在树的更下方,因此Casandra可以独立检查每个分支,而无需协调器节点下载整个数据集。
据此,以及我发现的其他数据结构文章,它们都表明只有在两棵Merkle树的根不同的情况下,才进行以下比根深的比较。我不确定文档是否正确描述了我可能理解的问题,或者实际上有错误?
我们知道在Haskell程序中,几乎每一个计算都会返回一些东西,并且这些返回值可以通过另一个计算来捕获,以对其应用更多的变换.因此,如果我们"平坦化"正常的Haskell程序,它应该是:
-- pure `a`: comes from Hask; not from file, network or any
-- other side-effected devices
a ? a' ? a'' ? a''' ? .... ? a_fin
Run Code Online (Sandbox Code Playgroud)
当然,这种纯粹的价值可能是"背景的".但我们仍然可以追踪交替的道路:
a ? m a ? m a' ? a'' ? n a''' ? ... ? z a_fin
Run Code Online (Sandbox Code Playgroud)
对我来说,这表明我们可以控制我们的程序,以避免副作用和其他"惊喜",这可能是由于缺少类型系统或我们自己造成的.但是当IO ()出现时,似乎有一个缺失:
--!! What happened between the IO () and the next computation ?
a ? m a ? m a' ? IO () >> b ? b' ? m b'
Run Code Online (Sandbox Code Playgroud)
在 …
haskell ×9
frp ×2
monads ×2
algorithm ×1
arrows ×1
cassandra ×1
free-monad ×1
list ×1
maybe ×1
merkle-tree ×1
performance ×1
purescript ×1
quickcheck ×1
typeclass ×1
types ×1