小编Rot*_*sor的帖子

不是Functor/Functor/Applicative/Monad的好例子?

在向某人解释什么是类型类X时,我很难找到正好是X的数据结构的好例子.

所以,我请求示例:

  • 一个不是Functor的类型构造函数.
  • 一个类型构造函数,它是一个Functor,但不是Applicative.
  • 一个类型构造函数,它是Applicative,但不是Monad.
  • Monad的类型构造函数.

我认为Monad到处都有很多例子,但Monad的一个很好的例子与之前的例子有一些关系可以完成图片.

我寻找彼此相似的示例,区别仅在于属于特定类型类的重要方面.

如果有人能够设法在这个层次结构的某个地方隐藏一个Arrow的例子(它是在Applicative和Monad之间吗?),那也会很棒!

monads haskell functor applicative

202
推荐指数
5
解决办法
1万
查看次数

为什么堆栈溢出仍然存在问题?

多年来这个问题让我很困惑,考虑到这个网站的名字,这是值得一提的地方.

为什么我们程序员仍然有这个StackOverflow问题?

为什么在每个主要语言中线程堆栈内存都必须在创建线程时静态分配?

我将在C#/ Java的上下文中发言,因为我最常使用它们,但这可能是一个更广泛的问题.

固定堆栈大小会导致巨大的问题:

  • 除非你绝对确定递归的深度很小,否则无法编写递归算法.递归算法的线性存储器复杂性通常是不可接受的.
  • 没有廉价的方法来启动新线程.您必须为堆栈分配大量内存来考虑线程的所有可能用途.
  • 即使您不使用非常深的递归,由于堆栈大小是任意固定数,您总是有可能耗尽堆栈空间.考虑到StackOverflow通常是不可恢复的,这是我眼中的一个大问题.

现在,如果堆栈动态调整大小,上面的所有问题都会大大减轻,因为堆栈溢出只有在存在内存溢出时才有可能.

但事实并非如此.为什么?现代CPU有一些基本限制会使其变得不可能/效率低下吗?如果你考虑重新分配所带来的性能ArrayList损失,它应该是可以接受的,因为人们一直使用结构而不会遭受太多痛苦.

所以,问题是,我错过了什么,StackOverflow不是问题,或者我错过了什么,有很多语言有动态堆栈,还是有一些很大的原因让这个不可能/难以实现?

编辑: 有人说性能会是个大问题,但请考虑一下:

  • 我们保持编译后的代码不变.堆栈访问保持不变,因此"通常情况"性能保持不变.
  • 我们处理CPU异常,当代码试图访问未分配的内存并启动我们的"重新分配"例程时会发生这种异常.重新分配不会频繁,因为<将您通常的ArrayList参数放在此处>.应该在大多数保护模式CPU上工作而不会降低性能.没有?

stack programming-languages memory-management

43
推荐指数
5
解决办法
1719
查看次数

Haskell中关系数据的安全建模

我发现想要在我的功能程序中建模关系数据是很常见的.例如,在开发网站时,我可能希望使用以下数据结构来存储有关我的用户的信息:

data User = User 
  { name :: String
  , birthDate :: Date
  }
Run Code Online (Sandbox Code Playgroud)

接下来,我想存储有关用户在我的网站上发布的消息的数据:

data Message = Message
  { user :: User
  , timestamp :: Date
  , content :: String
  }
Run Code Online (Sandbox Code Playgroud)

此数据结构存在多个问题:

  • 我们无法区分具有相似姓名和出生日期的用户.
  • 用户数据将在序列化/反序列化时重复
  • 比较用户需要比较他们的数据,这可能是昂贵的操作.
  • 对字段的更新User是脆弱的 - 您可能忘记更新User数据结构中的所有事件.

这些问题是可管理的,而我们的数据可以表示为树.例如,您可以像这样重构:

data User = User
  { name :: String
  , birthDate :: Date
  , messages :: [(String, Date)] -- you get the idea
  }
Run Code Online (Sandbox Code Playgroud)

但是,可以将数据整形为DAG(想象任何多对多关系),甚至可以作为一般图形(好的,也许不是).在这种情况下,我倾向于通过在Maps中存储我的数据来模拟关系数据库:

newtype Id a = Id Integer
type Table a = …
Run Code Online (Sandbox Code Playgroud)

haskell relational-database type-safety in-memory-database

37
推荐指数
4
解决办法
3647
查看次数

插入新绑定时是否复制了整个Map?

我想更好地理解例如Data.Map的实习生.当我在Map中插入一个新的绑定时,由于数据的不变性,我得到一个与旧数据结构加上新绑定相同的新数据结构.

我想了解这是如何实现的.编译器最终是通过使用数百万个绑定复制整个数据结构来实现的吗?通常可以说可变数据结构/数组(例如Data.Judy)或命令式编程语言在这种情况下表现更好吗?在字典/键值存储方面,不可变数据是否具有任何优势?

haskell

18
推荐指数
3
解决办法
599
查看次数

教会编码的实际原因

教会编码(又名访客模式)是一种将数据表示为函数的方式:而不是

data T = C1 F1 F2 | C2 F3 F4
Run Code Online (Sandbox Code Playgroud)

你可以定义

data T = T (forall r. (F1 -> F2 -> r) -> (F3 -> F4 -> r) -> r)
Run Code Online (Sandbox Code Playgroud)

.虽然将任何东西表示为函数的能力很好,但我一直认为第一个版本更可取,因为它更清晰,并且不需要语言扩展(显式forall).但是,您有时可以在公共图书馆中找到教会编码的数据.使用它有什么好处?

公共图书馆中教会编码的例子:

haskell church-encoding

14
推荐指数
1
解决办法
540
查看次数

合并的方式 - 排序比插入排序更快困惑我

刚刚在Haskell的排序算法中弄湿了我的脚.我已经实现了insert-sort和merge-sort

insert_sort :: (Ord a, Show a) => [a] -> [a]
insert_sort keys = foldr f [] keys
           where f key []        = [key]
                 f key acc       = insert key acc
                 insert y []     = [y]
                 insert y (x:xs)
                     | x < y     = x : insert y xs
                     | otherwise = y : x : xs

merge_sort :: (Ord a, Show a) => [a] -> [a]
merge_sort (x:[]) = [x]
merge_sort keys   = merge  (merge_sort (take len keys)) (merge_sort …
Run Code Online (Sandbox Code Playgroud)

sorting algorithm haskell lazy-evaluation

13
推荐指数
2
解决办法
1726
查看次数

如何系统地避免Scala中的不安全模式匹配?

考虑以下破坏的功能:

def sum (list : Seq[Int]) : Int = list match {
  case Nil => 0
  case head :: tail => head + sum(tail)
}
Run Code Online (Sandbox Code Playgroud)

在这里,该函数应该与a一起使用List[Int],但是被重构为接受Seq[Int],因此在没有编译器注意的情况下被破坏.

Scala不完整模式匹配检测中的这个空洞使得它几乎无用.

我想有办法系统地发现这些问题.具体来说,我希望编译器在每个instanceof引导模式匹配时发出错误/警告,即我只想在密封层次结构和自定义匹配器上允许模式匹配.

是否存在用于对模式匹配安全性进行保守(而不是任意)检查的现有编译器选项/插件?

scala pattern-matching non-exhaustive-patterns

12
推荐指数
1
解决办法
1297
查看次数

C++中是否可以使用无状态访问者模式?

我试图将以下Haskell代码转换为C++:

data List t = Nil | Cons t (List t)
Run Code Online (Sandbox Code Playgroud)

将代数数据类型直接转换为无状态访问者模式会产生以下Java代码

interface List<T> {
  <R> R accept(ListVisitor<T,R> v);
}

interface ListVisitor<T,R> {
  R visitNil();
  R visitCons(T head, List<T> tail);
}

class Nil<T> implements List<T> {
  @Override
  public <R> R accept(ListVisitor<T,R> v) {
    return v.visitNil();
  }
}

class Cons<T> implements List<T> {
  public final T head;
  public final List<T> tail;
  public Cons(T head, List<T> tail) {
    this.head = head;
    this.tail = tail;
  }
  @Override
  public <R> R accept(ListVisitor<T,R> v) { …
Run Code Online (Sandbox Code Playgroud)

c++ templates visitor stateless

11
推荐指数
1
解决办法
1015
查看次数

如何在Haskell中将小数分解为Rational?

我一直在参加一个编程竞赛,其中一个问题的输入数据包括十进制格式的小数:0.75就是一个例子.

解析它Double是微不足道的(我可以用read它),但精度的损失是痛苦的.人们需要非常小心地进行Double比较(我没有),这似乎是多余的,因为Rational在Haskell中有一个数据类型.

当试图使用它时,我发现read一个Rational人必须提供以下格式的字符串:numerator % denominator,我显然没有.

所以,问题是:

解析分数的十进制表示形式的最简单方法是什么Rational

还应考虑外部依赖项的数量,因为我无法在在线评判中安装其他库.

parsing haskell decimal rational-numbers

10
推荐指数
1
解决办法
3294
查看次数

NoMonomorphismRestriction有助于保持共享?

当我偶然发现这种奇怪的行为时,我试图回答关于多态性与共享的另一个问题.

在GHCi中,当我明确定义一个多态常量时,它没有得到任何共享,这是可以理解的:

> let fib :: Num a => [a]; fib = 1 : 1 : zipWith (+) fib (tail fib)
> fib !! 30
1346269
(5.63 secs, 604992600 bytes)
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我试图通过省略类型签名并禁用单态限制来实现相同的目标,那么我的常量会突然被分享!

> :set -XNoMonomorphismRestriction
> let fib = 1 : 1 : zipWith (+) fib (tail fib)
> :t fib
fib :: Num a => [a]
> fib !! 50
20365011074
(0.00 secs, 2110136 bytes)
Run Code Online (Sandbox Code Playgroud)

为什么?!

呃...当使用优化编译时,即使禁用单态限制也很快.

haskell ghc data-sharing monomorphism-restriction

10
推荐指数
1
解决办法
613
查看次数