javascript

java

python

c#

android

node.js

reactjs

c++

php

html

jquery

css

git

.net

ios

ruby-on-rails

sql

c

string

ruby

基准测试-实际表现更好的是什么? Haskell或OCam

在过去的18个月中,我开始学习函数式编程,从学习OCaml到现在的Haskell已有数周。 现在,我要进行下一步并实现一些实际的应用程序:一个简单的实时地形编辑器。 我已经编写了许多实时地形渲染引擎,因此这是一个熟悉的主题。 所使用的递归算法和数据结构似乎非常适合功能实现。

由于这是一个实时应用程序,所以我自然在寻找可以得到的最佳性能。 现在,OCaml的一些支持者(IMHO非常烦人)经常反对Haskell比OCaml或F#慢。 但是根据《计算机语言基准测试》,Haskell经常击败OCaml,即使只是很小的一部分-仍然存在问题,该基准测试仅包含非常具体的示例。

正确的做法当然是用两种语言实施该程序并进行比较,但是我根本不想做双重工作。

但是也许其他人在OCaml和Haskell中做了类似的应用并给出了一些数字?

trans by 2019-11-18T12:44:27Z

Has中Priority Queue实现的比较

Haskell似乎有几种可用的优先级队列实现。 例如,有:

  • Data.PriorityQueue.FingerTree(在hackage的fingertree-0.0.1.0中)
  • Data.PurePriorityQueue(在hackage的pure-priority-queue-0.14中)

两者似乎都是纯优先级队列数据结构。 前者基于手指树,这是我不熟悉的数据结构。 后者是Data.Map的包装。 还有

  • Data.Heap(在hackage的heap-1.0.0中)

它定义了纯粹的功能堆数据结构,从中可以简单地创建优先级队列。 。 也有

  • Data.Heap(在hackage中为heaps-0.2)
  • Data.MeldableHeap(关于hackage,在meldable-heap-2.0.3中)

两者都使用Brodal / Okasaki数据结构实现了纯功能可熔堆,我相信这类似于非纯功能领域中的二项式堆数据结构。

(哦,还有

  • Data.PriorityQueue(在hackage的priority-queue-0.2.2中)

我的功能不清楚,但似乎与建立附加到monad的优先级队列有关,并且无论如何似乎都建立在Data.Map之上。 在这个问题中,我只关心功能优先级队列,因此我认为priority-queue-0.2.2包无关紧要。 但是,如果我错了,请纠正我!)

对于我正在构建的项目,我需要一个纯功能优先队列数据结构。 我想知道在我决定黑客提供的财富所带来的尴尬之间,是否有人可以提供任何智慧的话。 特别:

  1. 假设我希望在纯功能/不变的演示中实现除传统优先级队列插入和extract-min操作之外的功能。 上面提到的软件包的优缺点是什么? 有没有人有使用过“生气”的经验? 在性能上要权衡些什么? 可靠性? 哪些被其他人使用更广泛? (使用这些代码可能会使其他人更容易阅读我的代码,因为他们将更可能熟悉该库。)在它们之间做出决定之前,我还应该了解其他事情吗?
  2. 如果我还想有效地合并优先级队列,那该怎么办? (我不参与该项目,但我想添加此内容,但会使SO问题对以后的读者更加有用。)
  3. 还有其他我错过的优先级队列软件包吗?
trans by 2019-11-18T07:46:32Z

类型-Haskell的DataKinds扩展是什么?

我试图找到对DataKinds扩展的解释,这对我来说很有意义,因为仅阅读过Learn Has a Haskell。 我所学到的东西是否有对我有意义的标准资源?

编辑:例如文档说

通过-XDataKinds,GHC自动将每个合适的数据类型提升为一种类型,并将其(值)构造函数提升为类型构造函数。 以下类型

并给出例子

data Nat = Ze | Su Nat

产生以下种类和类型的构造函数:

Nat :: BOX
Ze :: Nat
Su :: Nat -> Nat

我不明白这一点。 尽管我不明白BOX是什么意思,但是语句Ze :: Nat和261700972053161616770似乎已经说明Ze和Su是正常数据构造函数的情况已经完全符合ghci的预期

Prelude> :t Su
Su :: Nat -> Nat
trans by 2019-11-16T17:01:25Z

haskell-为n维网格类型编写共同或联合

使用类型级自然变量的典型定义,我定义了一个n维网格。

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}

data Nat = Z | S Nat

data U (n :: Nat) x where
  Point :: x -> U Z x
  Dimension :: [U n x] -> U n x -> [U n x] -> U (S n) x

dmap :: (U n x -> U m r) -> U (S n) x -> U (S m) r
dmap f (Dimension ls mid rs) = Dimension (map f ls) (f mid) (map f rs)

instance Functor (U n) where
  fmap f (Point x) = Point (f x)
  fmap f d@Dimension{} = dmap (fmap f) d

现在,我想使其成为Comonad的一个实例,但是我不能完全包绕它。

class Functor w => Comonad w where
  (=>>)    :: w a -> (w a -> b) -> w b
  coreturn :: w a -> a
  cojoin   :: w a -> w (w a)

  x =>> f = fmap f (cojoin x)
  cojoin xx = xx =>> id

instance Comonad (U n) where
  coreturn (Point x) = x
  coreturn (Dimension _ mid _) = coreturn mid

  -- cojoin :: U Z x -> U Z (U Z x)
  cojoin (Point x) = Point (Point x)
  -- cojoin ::U (S n) x -> U (S n) (U (S n) x)
  cojoin d@Dimension{} = undefined

  -- =>> :: U Z x -> (U Z x -> r) -> U Z r
  p@Point{} =>> f = Point (f p)
  -- =>> :: U (S n) x -> (U (S n) x -> r) -> U (S n) r
  d@Dimension{} =>> f = undefined

在n维网格上使用cojoin将产生n维网格的n维网格。 我想提供一个与此实例相同的实例,即在(x,y,z)处的联合网格的值应该是专注于(x,y,z)的原始网格。 为了适应该代码,看来我们需要验证n,以便执行n“ fmaps”和2616565005625590590787“ rolls”。 您不必那样做,但是如果有帮助,就可以了。

trans by 2019-11-16T09:39:11Z

嵌入式-将Haskell用于大型实时系统:如何(如果?)?

我一直很想知道是否有可能将Haskell的功能应用于嵌入式实时世界,并且在谷歌搜索中找到了Atom软件包。 我假设在复杂的情况下,代码可能具有所有经典的C错误-崩溃,内存损坏等,然后需要追溯到原始的Haskell代码,造成了他们。 因此,这是问题的第一部分:“如果您具有Atom的经验,您如何处理调试已编译的C代码中的低级bug并将其修复为Haskell原始代码的任务?”

我在Atom上搜索了更多示例,该博客文章提到了生成的C代码22KLOC(显然没有代码:),其中包括一个玩具。 这个和这个引用有一些更实际的代码,但这就是到此为止。 我在主题中添加“相当大”的原因是,如果您可以分享使用300KLOC +范围内生成的C代码的经验,我最感兴趣。

由于我是Haskell的新手,很明显,由于未知的未知数,可能还有其他找不到的方法,因此,在此领域进行自我教育的其他任何指示都将不胜感激-这是问题的第二部分- “如果在Haskell中进行实时开发,还有其他一些实用的方法吗?”。 如果多核也出现在图片中,那是一个额外的优势:-)

(关于为此目的使用Haskell本身:根据我在此博客文章中所读到的内容,Haskell中的垃圾回收和惰性使它在确定性调度方面变得相当不确定,但也许在两年后发生了一些变化。真实世界中关于Haskell编程的问题 是我可以找到的最接近该主题的位置)

注意:上面的“实时”将更接近“硬实时”-我很好奇是否可以确保不执行主要任务时的暂停时间在0.5毫秒以下。

trans by 2019-11-14T21:44:58Z

haskell-为什么seq不好?

Haskell具有一个神奇的函数,名为seq,该函数可以接受任何类型的参数并将其简化为弱头范式(WHNF)。

我读过一些资料(不是我现在记得他们是谁...),它们声称“多态seq不好”。 他们以什么方式“不好”?

类似地,还有seq函数,该函数将自变量简化为标准格式(NF)。 但这是一个类方法。 它不适用于任意类型。 在我看来,“可以改变”语言规范以将其作为内置的原语提供,这似乎是“显而易见的”,类似于rnf。据推测,这比仅具有par还要“糟糕得多”。?

最后,有人建议赋予seqrnfpar和类似的功能与id函数相同的类型,而不是现在的const函数,将是一种改进。 怎么会这样?

trans by 2019-11-13T18:52:16Z

范围-在Haskell中,什么时候与let一起使用?

在下面的代码中,我可以在最后一句前面加上where。 它会改变什么吗?

另一个问题:如果我决定将where放在最后一句的前面,是否需要缩进?

我尝试了不缩进并且拥抱抱怨

do {...}中的最后一个生成器必须是表达式

import Data.Char
groupsOf _ [] = []
groupsOf n xs = 
    take n xs : groupsOf n ( tail xs )

problem_8 x = maximum . map product . groupsOf 5 $ x
main = do t <- readFile "p8.log" 
          let digits = map digitToInt $concat $ lines t
          print $ problem_8 digits

编辑

好的,所以人们似乎听不懂我在说什么。 让我改一下:给定上面的上下文,以下两个是否相同?

1。

let digits = map digitToInt $concat $ lines t
print $ problem_8 digits

2。

let digits = map digitToInt $concat $ lines t
in print $ problem_8 digits

关于where中声明的绑定范围的另一个问题:我在这里读到:

where条款。

有时,将绑定范围限制在几个保护方程式上很方便,这需要where子句:

f x y  |  y>z           =  ...
       |  y==z          =  ...
       |  y<z           =  ...
     where z = x*x

请注意,这不能通过let表达式来完成,let表达式只能在其所包围的表达式范围内。

我的问题:因此,最后一个打印短语不应看到可变数字。 我在这里想念什么吗?

trans by 2019-11-13T17:27:02Z

协方差-为什么在Haskell(与Scala或C#相对)中没有太多关于协方差和对数方差的讨论?

我知道类型是什么协方差和矛盾。 我的问题是为什么我在研究Haskell(与Scala相对)时还没有遇到关于这些概念的讨论?

似乎Haskell查看类型的方式与Scala或C#的方式根本不同,我想指出一下这种差异是什么。

也许我错了,但我还没有学到足够的Haskell :-)

trans by 2019-11-11T14:29:24Z

如何在Haskell中编写多行字符串?

假设我有带换行符的字符串文字:

file :: String
file = "the first line\nthe second line\nthe third line"

有什么办法可以这样写吗?

file :: String
file = "the first line
        the second line
        the third line"

上面的尝试导致此错误:

factor.hs:58:33:
    lexical error in string/character literal at character '\n'
Failed, modules loaded: none.
trans by 2019-11-10T14:21:45Z

haskell-纯功能数据结构的好处是什么?

关于数据结构的文本很多,数据结构的代码库也很多。 我了解纯功能数据结构更容易推论。 但是,我很难理解在实用代码中使用纯功能数据结构(无论是否使用功能编程语言)相对于命令性代码所具有的现实优势。 有人可以提供一些纯粹的功能数据结构具有优势的现实案例吗?为什么?

像我这样的例子使用了programming_language中的data_structure_name来执行应用程序,因为它可以执行某些操作。

谢谢。

PS:我所说的纯功能数据结构与持久性数据结构不同。 持久数据结构是不变的数据结构??? 另一方面,纯功能数据结构是纯操作的数据结构。

trans by 2019-11-10T01:00:28Z

语法-如何在Has中导入.hs文件

我制作了一个名为.hs的文件。该文件包含一个用于测量另一个函数执行时间的函数。

有没有一种方法可以将.hs文件导入另一个Haskell脚本?

我想要类似的东西:

module Main where
import C:\Haskell\time.hs

main = do
    putStrLn "Starting..."
    time $ print answer
    putStrLn "Done."

在“ time.hs”中将时间定义为:

module time where
Import <necessary modules>

time a = do
start <- getCPUTime
v <- a
end   <- getCPUTime
let diff = (fromIntegral (end - start)) / (10^12)
printf "Computation time: %0.3f sec\n" (diff :: Double)
return v

我不知道如何导入或加载单独的.hs文件。 导入之前是否需要将time.hs文件编译成模块?

trans by 2019-11-09T05:15:04Z

haskell-是否具有将元素的嵌套列表展平的功能?

我怎样才能展平这样的嵌套列表:

[1, 2, 3, 4] == flatten [[[1,2],[3]],[[4]]]
trans by 2019-11-08T17:42:19Z

并发-为什么Haskell中没有隐式并行性?

Haskell是实用且纯净的,因此基本上它具有编译器能够处理隐式并行性所需的所有属性。

考虑下面这个简单的例子:

f = do
  a <- Just 1
  b <- Just $ Just 2
  -- ^ The above line does not utilize an `a` variable, so it can be safely
  -- executed in parallel with the preceding line
  c <- b
  -- ^ The above line references a `b` variable, so it can only be executed
  -- sequentially after it
  return (a, c)
  -- On the exit from a monad scope we wait for all computations to finish and 
  -- gather the results

执行计划的示意图可以描述为:

               do
                |
      +---------+---------+
      |                   |
  a <- Just 1      b <- Just $ Just 2
      |                   |
      |                 c <- b
      |                   |
      +---------+---------+
                |
           return (a, c)

为什么在编译器中还没有实现带有标志或编译指示的此类功能? 实际原因是什么?

trans by 2019-11-08T09:52:30Z

为什么用null函数代替== []检查Haskell中的空列表?

我正在阅读“了解Haskell的伟大成就!”的“入门”一章。 它说:

null检查列表是否为空。 如果是,则返回null,否则返回null。使用此函数代替null(如果您有一个名为null的列表)

我在ghci中尝试过:

xs = []      -- and then,

xs == []
null xs

他们都是null

我想知道有什么区别。

我应该使用null函数而不是== [],为什么?

trans by 2019-11-07T22:36:36Z

haskell-OOP接口和FP类型类之间的区别

可能重复:
Java接口和Haskell类型类:区别和相似之处?

当我开始学习Haskell时,我被告知类型类比接口更强大。

一年后,我广泛使用了接口和类型类,但还没有看到有关它们之间的区别的示例或说明。 这要么不是自然而然的启示,要么是我错过了一些显而易见的事情,或者实际上并没有真正的区别。

搜索互联网并没有发现任何实质性的东西。 所以,你有答案吗?

trans by 2019-11-04T00:16:07Z

函数式编程-在Has中维护复杂状态

假设您正在Haskell中建立一个相当大的模拟。 有许多不同类型的实体,其属性会随着仿真的进行而更新。 举例来说,假设您的实体称为“猴子”,“大象”,“熊”等。

您维护这些实体状态的首选方法是什么?

我想到的第一个也是最明显的方法是:

mainLoop :: [Monkey] -> [Elephant] -> [Bear] -> String
mainLoop monkeys elephants bears =
  let monkeys'   = updateMonkeys   monkeys
      elephants' = updateElephants elephants
      bears'     = updateBears     bears
  in
    if shouldExit monkeys elephants bears then "Done" else
      mainLoop monkeys' elephants' bears'

Monkey函数签名中明确提及每种类型的实体已经很丑陋。 您可以想象,如果拥有20种实体,它将变得多么可怕。 (对于复杂的模拟,这不是不合理的20。)因此,我认为这是不可接受的方法。 但是它的优点是,像Elephant这样的函数在其工作中非常明确:它们获取Monkey列表并返回一个新列表。

因此,下一个想法是将所有内容都放到一个拥有所有状态的大数据结构中,从而清除Monkey的签名:

mainLoop :: GameState -> String
mainLoop gs0 =
  let gs1 = updateMonkeys   gs0
      gs2 = updateElephants gs1
      gs3 = updateBears     gs2
  in
    if shouldExit gs0 then "Done" else
      mainLoop gs3

有人建议我们将Monkey包裹在State Monad中,然后在Elephant中致电Elephant,等等。 有人宁愿建议我们使用功能组合对其进行清理。 我想也可以。 (顺便说一句,我是Haskell的新手,所以也许我对此有些误解。)

但是问题是,像Monkey这样的函数无法从其类型签名中提供有用的信息。 您不能真正确定它们的作用。 当然,Elephant是一个描述性的名称,但这实在没有什么可安慰的。 当我传递一个神物并说“请更新我的全局状态”时,我感到我们回到了当务之急。 感觉就像全局变量一样,您可以使用它的名字:您拥有一个对全局状态有所作为的函数,您将其称为“函数”,并且希望获得最佳状态。 (我想您仍然避免在命令式程序中全局变量会出现一些并发问题。但是,并发并不是全局变量几乎唯一的错。)

另一个问题是:假设对象需要交互。 例如,我们有一个这样的函数:

stomp :: Elephant -> Monkey -> (Elephant, Monkey)
stomp elephant monkey =
  (elongateEvilGrin elephant, decrementHealth monkey)

假设在Monkey中有一个叫它的名字,因为这是我们检查是否有大象在任何猴子踩踏的地方。 在这种情况下,您如何优雅地将更改传播给猴子和大象? 在我们的第二个示例中,Elephant接收并返回了一个上帝对象,因此它可以同时影响这两个更改。 但是,这只会进一步模糊我的观点,并强化我的观点:有了上帝的对象,您实际上只是在改变全局变量。 而且,如果您不使用God对象,则不确定如何传播这些类型的更改。

该怎么办? 当然,许多程序都需要管理复杂的状态,所以我猜想有一些众所周知的方法可以解决此问题。

仅出于比较的目的,这就是我如何解决OOP世界中的问题。 将有MonkeyElephant等对象。 我可能会有类方法来对所有活体动物进行查找。 也许您可以按位置,按ID进行查找。 由于查找函数基础的数据结构,它们将在堆上保持分配状态。 (我假设是GC或引用计数。)它们的成员变量会一直变异。 任何类别的任何方法都将能够突变任何其他类别的任何活体动物。 例如。 Elephant可以具有stomp方法,该方法将减少传入的Monkey对象的运行状况,并且无需通过该方法

同样,在Erlang或其他面向参与者的设计中,您可以相当优雅地解决这些问题:每个参与者都维护自己的循环并因此维护自己的状态,因此您永远不需要上帝对象。 消息传递允许一个对象的活动触发其他对象的更改,而无需一堆东西一直返回到调用堆栈。 但是我听说它说Haskell的演员不满意。

trans by 2019-11-03T18:46:44Z

scala-什么是monoid同态?

我已经从Monoid Morphisms,Products和Coproducts中阅读了有关Monoid同态的知识,并且无法理解100%。

作者说(强调原文):

String函数从Int映射到length,同时保留   体结构。 这样的功能,可以将一个半身像映射到   另一个以这种保存方式被称为“ monoid同态”。 在   一般,适用于等分体String => IntInt,同构f: M => N,以及所有值   x:My:M,以下等式成立:

String

他的意思是说,由于数据类型StringInt是monoid,并且函数length映射了String => Int保留了monoid结构(Int),所以被称为monoid同态,对吗?

trans by 2019-11-03T06:25:54Z

haskell-模式匹配和后卫有什么区别?

我对Haskell和一般的函数式编程非常陌生。 我的问题很基本。 模式匹配和后卫有什么区别?

使用模式匹配功能

check :: [a] -> String
check [] = "Empty"
check (x:xs) = "Contains Elements"

使用防护功能

check_ :: [a] -> String
check_ lst
    | length lst < 1 = "Empty"
    | otherwise = "Contains elements"

在我看来,模式匹配和后卫基本上是相同的。 两者都评估条件,如果为true,则将执行与该条件挂钩的表达式。 我的理解正确吗?

在此示例中,我可以使用模式匹配或防护来获得相同的结果。 但是有一些事情告诉我,我在这里错过了一些重要的事情。 我们可以总是用另一个替换吗?

有人可以举例说明模式匹配优先于警卫,反之亦然吗?

trans by 2019-10-14T23:14:31Z

haskell-文件夹如何工作?

谁能解释foldr如何工作?

请看以下示例:

Prelude> foldr (-) 54 [10, 11]
53
Prelude> foldr (\x y -> (x+y)/2) 54 [12, 4, 10, 6]
12.0

我对这些处决感到困惑。 有什么建议么?

trans by 2019-10-14T20:41:21Z

scala-集,函子和等式混淆

最近在讨论有关集合的问题,该集合在Scala中支持Set方法以及该方法如何导致错误,例如

scala> val words = Set("one", "two", "three")
scala> words zip (words map (_.length))
res1: Set[(java.lang.String, Int)] = Set((one,3), (two,5))

我认为很明显Sets不应该支持Functor241操作,因为这些元素没有顺序。 但是,有人提出问题是2568268482429329322242并不是真正的函子,不应使用Functor243方法。 当然,您可以通过映射集合来使自己陷入困境。 现在切换到Haskell,

data AlwaysEqual a = Wrap { unWrap :: a }

instance Eq (AlwaysEqual a) where
    _ == _ = True

instance Ord (AlwaysEqual a) where
    compare _ _ = EQ

现在在ghci

ghci> import Data.Set as Set
ghci> let nums = Set.fromList [1, 2, 3]
ghci> Set.map unWrap $ Set.map Wrap $ nums
fromList [3]
ghci> Set.map (unWrap . Wrap) nums
fromList [1, 2, 3]

因此Set无法满足函子定律

    fmap f . fmap g = fmap (f . g)

可以说这不是2568268482429329322241s上的Set操作的失败,而是我们定义的Eq实例的失败,因为它不遵守替换法则,即A和B上的两个256826848242932222243和 然后映射Monad

    if x == y (on A) then f x == f y (on B)

不适用于Set(例如,考虑Functor)。

替代法是否是我们应该遵守的2568268482429329322240类型的明智法? 当然,我们的2568268482429329322241类型也遵守了其他平等法则(对对称性,传递性和反射性的满足很少),因此替代是我们唯一遇到麻烦的地方。

对我来说,替代2568268482429329322240类似乎是非常理想的属性。 另一方面,最近Reddit讨论中的一些评论包括

“替换似乎比必要的要强大,并且基本上是在商谈类型,对使用该类型的每个函数都提出了要求。”

-Godofpumpkins

“我也确实不希望替换/同余,因为我们有很多合法的用途要与之相等,但它们在某种程度上是可以区分的。”

-sclv

“替代只为结构平等而成立,但没有人坚持认为Set是结构性的。”

-爱德华

这三个在Haskell社区中都是众所周知的,因此我很犹豫反对它们,并坚持要求我的Set类型具有可替换性!

反对Set的另一个论点是Functor-众所周知,作为Eq242允许您在保留形状的同时变换“集合”的“元素”。 例如,Haskell Wiki上的此引用(请注意FunctorMonad的概括)

“其中2568268468482429322240使您能够遍历结构处理元素,但丢弃形状,而Functor241可让您在保留形状的同时做到这一点,例如,输入新的值。”

Set是关于按原样保留该结构。”

在现实世界中

“ ... [仿函数]必须保留形状。集合的结构不应受到仿函数的影响;只有其包含的值才应更改。”

显然,任何Set的仿函数实例都可以通过减少集合中的元素数量来更改形状。

但是,似乎2568268482429329322240s确实应该是函子(暂时忽略了2568268482429329322241的要求-我认为这是由于我们渴望有效地使用集合而施加的人为限制,而不是对任何集合的绝对要求。例如,函数集 不管怎样,Oleg都展示了如何为Eq编写高效的Functor和Monad实例,这些实例不需要Functor约束)。 它们有很多不错的用途(对于不存在的2568268482429329322244实例也是如此)。

谁能解决这个烂摊子? Set应该是Functor吗? 如果是这样,那么对于违反Functor法则的潜力有何作用? Eq的法律应该是什么,它们如何与Functor特别是256826848244609999456的法律相互影响?

trans by 2019-10-14T02:03:10Z

1 2 3 4 5 6 7 8 9 10 11 12 13 下一页 共13页