Haskell(使用GHC
编译器)比你期望的要快很多.如果使用得当,它可以与低级语言保持密切联系.(Haskellers最喜欢的事情是尝试在C的5%范围内(或者甚至击败它,但这意味着你使用的是低效的C程序,因为GHC将Haskell编译为C).)我的问题是,为什么?
Haskell是声明性的,基于lambda演算.机器架构显然势在必行,粗略地基于图灵机.实际上,Haskell甚至没有具体的评估顺序.此外,您不必处理机器数据类型,而是始终生成代数数据类型.
最奇怪的是更高阶函数.你会认为动态创建函数并抛出它们会使程序变慢.但是使用更高阶函数实际上使Haskell更快.实际上,似乎要优化Haskell代码,你需要使它更优雅和抽象,而不是更像机器.如果Haskell的更高级功能没有改进,它们似乎甚至都不会影响它的性能.
很抱歉,如果这听起来不错,但这是我的问题:为什么Haskell(使用GHC编译)如此之快,考虑到它的抽象性质和与物理机器的差异?
注意:我说C和其他命令式语言有点类似于图灵机的原因(但不是Haskell类似于Lambda微积分)是因为在命令式语言中,你有一个有限数量的状态(也就是行号) ,以及磁带(ram),以便状态和当前磁带确定对磁带做什么.有关从图灵机到计算机的过渡,请参阅维基百科条目,图灵机等效项.
performance haskell lambda-calculus ghc higher-order-functions
你如何使用bash延续线?
我意识到你可以这样做:
echo "continuation \
lines"
>continuation lines
Run Code Online (Sandbox Code Playgroud)
但是,如果你有缩进代码,它不能很好地工作:
echo "continuation \
lines"
>continuation lines
Run Code Online (Sandbox Code Playgroud) 如果那样的return a = return b
话你能证明a=b
吗?当我使用时=
,我的意思是在法律和证据意义上,而不是Eq
阶级意义上.
我认识的每一个单子似乎都满足了这一点,我想不出一个有效的monad(Const a
不是一个算子和应用,而不是一个monad.)
python中的什么命令可以用来运行另一个python程序?它不应该等待子进程终止,而是继续.它也不需要记住它的子进程.
这篇文章是有文化的Haskell.只需输入像"pad.lhs"这样的文件ghci
就能运行它.
> {-# LANGUAGE GADTs, Rank2Types #-}
> import Control.Monad
> import Control.Monad.ST
> import Data.STRef
Run Code Online (Sandbox Code Playgroud)
好的,所以我能够想出如何ST
用纯代码表示monad.首先,我们从我们的引用类型开始.它的具体价值并不重要.最重要的是PT s a
不应该与任何其他类型同构forall s
.(特别是,它既不应该同形()
也不应该同形Void
.)
> newtype PTRef s a = Ref {unref :: s a} -- This is defined liked this to make `toST'` work. It may be given a different definition.
Run Code Online (Sandbox Code Playgroud)
那种为s
是*->*
,但现在不是真的很重要.对于我们所关心的一切,它可能是多面手的.
> data PT s a where
> MkRef :: a -> PT s …
Run Code Online (Sandbox Code Playgroud) 好吧,让我们说你有类型
newtype Dual f a = Dual {dual :: forall r. f(a -> r)->r}
Run Code Online (Sandbox Code Playgroud)
事实证明,什么时候f
是Comonad,Dual f
是Monad(有趣的运动).它是否相反?
您可以定义fmap ab (Dual da) = Dual $ \fb -> da $ fmap (. ab) fb
和extract (Dual da) = da $ return id
,但我不知道如何定义duplicate
或extend
.
这甚至可能吗?如果没有,那么证据不存在(是否有一个特定的Monad m
,你可以证明Dual m
它不是一个comonad)?
一些观察:
Dual IO a
基本上Void
(并且Const Void
是有效的Comonad
).
Dual m a
为MonadPlus m
是 Void
(只使用dual mzero
). …
给定一个仿函数(或任何类型的构造函数)f
,我们可以获得该仿函数的"版本",该版本不包含其参数的值.我们只是定义newtype NoArg f = NoArg (f Void)
.例如:
NoArg []
只是空名单.NoArg Maybe
没什么.NoArg (Either e)
只是e
.NoArg (Identity)
是Void
.NoArg IO
是一个永远产生效果的IO动作(如服务器).Functor f => NoArg (Free f)
是Fix f
.我的问题是,如果我们能做到的对面,并创建一个类型,函子的构造函数并使用它的参数.在形式上,Arg :: (* -> *) -> (* -> *)
应该是有一个术语forall a. Arg f a -> a
或等同的Arg f Void -> Void
.例如:
Arg [] a
是非空类型列表的类型a
.Arg Maybe a
只是a …
haskell types functional-programming functor type-constructor
有没有人知道一个只允许一定时间执行函数的函数.像这样的类型签名的东西.
limited::Int->(a->b)->a->IO (Maybe b)
Run Code Online (Sandbox Code Playgroud)
我想不出如何实现,我找不到它.我问的原因是我要列出所有可能的Brainfuck程序,我想过滤那些花费太长时间的程序.
> {-# LANGUAGE DeriveFunctor, Rank2Types, ExistentialQuantification #-}
Run Code Online (Sandbox Code Playgroud)
任何归纳类型都是这样定义的
> newtype Ind f = Ind {flipinduct :: forall r. (f r -> r) -> r}
> induction = flip flipinduct
Run Code Online (Sandbox Code Playgroud)
induction
有类型(f a -> a) -> Ind f -> a
.这种称为共同诱导的概念是双重的.
> data CoInd f = forall r. Coinduction (r -> f r) r
> coinduction = Coinduction
Run Code Online (Sandbox Code Playgroud)
coinduction
有类型(a -> f a) -> a -> CoInd f
.注意如何induction
和coinduction
是双重的.作为归纳和coinductive数据类型的示例,请查看此仿函数.
> data StringF rec = Nil …
Run Code Online (Sandbox Code Playgroud) recursion haskell functional-programming induction coinduction
我们可以将continuation monad变换器定义为
data Cont r m a = Cont {run :: (a -> m r) -> m r}
Run Code Online (Sandbox Code Playgroud)
Cont r m
如果m
是Alternative
via 的成员,我们可以给出Alternative实例
empty = Cont $ \f -> empty
ca <|> cb = Cont $ \f -> run ca f <|> run cb f
Run Code Online (Sandbox Code Playgroud)
然后允许some
并many
采用他们的默认方法.我的问题是,我们可以定义some
并many
在以下方面m
的some
和many
,而不是默认的定义是什么?显而易见的选择
some ca = Cont $ \f -> some $ run ca f
many ca = Cont …
Run Code Online (Sandbox Code Playgroud) continuations haskell typeclass applicative continuation-passing