javascript

java

python

c#

node.js

android

reactjs

c++

php

jquery

html

css

git

ruby-on-rails

.net

ios

sql

c

string

ruby

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

haskell-单态性限制是什么?

我对haskell编译器有时会推断出类型较少的类型感到困惑比我预期的多态,例如在使用无点定义时。

似乎问题出在“单态限制”上,默认情况下,较旧版本的编译器。

考虑以下haskell程序:

{-# LANGUAGE MonomorphismRestriction #-}

import Data.List(sortBy)

plus = (+)
plus' x = (+ x)

sort = sortBy compare

main = do
  print $ plus' 1.0 2.0
  print $ plus 1.0 2.0
  print $ sort [3, 1, 2]

如果使用plus进行编译,则不会获得任何错误,并且可执行文件的输出为:

3.0
3.0
[1,2,3]

如果我将plus主体更改为:

main = do
  print $ plus' 1.0 2.0
  print $ plus (1 :: Int) 2
  print $ sort [3, 1, 2]

我没有编译时错误,输出变为:

3.0
3
[1,2,3]

如预期的那样。 但是,如果我尝试将其更改为:

main = do
  print $ plus' 1.0 2.0
  print $ plus (1 :: Int) 2
  print $ plus 1.0 2.0
  print $ sort [3, 1, 2]

我收到类型错误:

test.hs:13:16:
    No instance for (Fractional Int) arising from the literal ‘1.0’
    In the first argument of ‘plus’, namely ‘1.0’
    In the second argument of ‘($)’, namely ‘plus 1.0 2.0’
    In a stmt of a 'do' block: print $ plus 1.0 2.0

当尝试使用不同的类型两次调用plus时,也会发生相同的情况:

main = do
  print $ plus' 1.0 2.0
  print $ plus 1.0 2.0
  print $ sort [3, 1, 2]
  print $ sort "cba"

产生以下错误:

test.hs:14:17:
    No instance for (Num Char) arising from the literal ‘3’
    In the expression: 3
    In the first argument of ‘sort’, namely ‘[3, 1, 2]’
    In the second argument of ‘($)’, namely ‘sort [3, 1, 2]’
  • 为什么plus突然认为ghci不是多态的并且需要plus'自变量?对plus的唯一引用是在Num a => a -> a -> a的应用程序中,那怎么回事该定义何时明显是多态的?
  • 为什么plus突然认为ghci需要plus'实例?

此外,如果我尝试将函数定义放入其自己的模块中,如下所示:

{-# LANGUAGE MonomorphismRestriction #-}

module TestMono where

import Data.List(sortBy)

plus = (+)
plus' x = (+ x)

sort = sortBy compare

编译时出现以下错误:

TestMono.hs:10:15:
    No instance for (Ord a0) arising from a use of ‘compare’
    The type variable ‘a0’ is ambiguous
    Relevant bindings include
      sort :: [a0] -> [a0] (bound at TestMono.hs:10:1)
    Note: there are several potential instances:
      instance Integral a => Ord (GHC.Real.Ratio a)
        -- Defined in ‘GHC.Real’
      instance Ord () -- Defined in ‘GHC.Classes’
      instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
      ...plus 23 others
    In the first argument of ‘sortBy’, namely ‘compare’
    In the expression: sortBy compare
    In an equation for ‘sort’: sort = sortBy compare
  • 为什么plus无法将多态类型ghci用于plus'
  • 为什么plusghciplus'不同? plus应该具有多态类型Num a => a -> a -> a,我真的看不出这有什么不同从sort的类型开始,但只有sort会引发错误。

最后一件事:如果我评论plus的定义,则文件将编译。 然而如果我尝试将其加载到ghci并检查得到的类型:

*TestMono> :t plus
plus :: Integer -> Integer -> Integer
*TestMono> :t plus'
plus' :: Num a => a -> a -> a

为什么plus的类型不是多态的?


这是有关Haskell中单态限制的规范问题如meta问题中所述。

trans by 2019-10-13T20:51:19Z

oop-为什么Haskell代数数据类型“封闭”?

如果我错了,请纠正我,但是Haskell中的代数数据类型似乎在许多用OO语言使用类和继承的情况下很有用。 但是有一个很大的区别:一旦声明了代数数据类型,就无法将其扩展到其他位置。 它是“关闭的”。 在OO中,您可以扩展已经定义的类。 例如:

data Maybe a = Nothing | Just a

我无法在以后不修改此声明的情况下以某种方式向该类型添加另一个选项。 那么这个系统有什么好处呢? OO方法似乎可以扩展得多。

trans by 2019-10-13T18:15:49Z

函数式编程-什么是“ n + k模式”,为什么在Haskell 2010中禁止使用它们?

当阅读Wikipedia在Haskell 2010上的条目时,我偶然发现了这一点:

-- using only prefix notation and n+k-patterns (no longer allowed in Haskell 2010)
factorial 0 = 1
factorial (n+1) = (*) (n+1) (factorial n)

“ n + k模式”是什么意思? 我想这是第二行,但是我不明白这可能有什么问题。 谁能解释那里的问题是什么? 为什么在Haskell 2010中不更允许使用这些n + k模式?

trans by 2019-10-13T00:00:43Z

haskell-如何减少.cabal文件的build-depends字段中的重复项?

这是一个.cabal文件:

Name:                myprogram
Version:             0.1
-- blah blah blah
Cabal-version:       >=1.9.2

Executable myprogram
  HS-source-dirs:       src
  Main-is:              Main.hs
  Build-depends:        attoparsec == 0.10.*,
                        base == 4.3.*,
                        -- long long list of packages

Test-Suite test
  HS-source-dirs:       test, src
  Type:                 exitcode-stdio-1.0
  Main-is:              Main.hs
  Build-depends:        attoparsec == 0.10.*,
                        base == 4.3.*,
                        -- long long list of packages
                        QuickCheck == 2.4.*

有什么办法可以用“与可执行文件相同,再加上QuickCheck”来替换测试套件的长版本依赖软件包?

编辑:版本信息。

  • cabal-dev 0.9
  • cabal-install 0.10.2
  • Cabal库1.10.2.0
  • GHC 7.0.4
  • Haskell平台2011.4.0.0
trans by 2019-10-11T20:16:36Z

不可知的语言-使用软件事务存储有任何现实世界的经验吗?

似乎最近对STM(软件事务存储)框架和语言扩展有了越来越高的兴趣。 Clojure特别具有出色的实现,它使用MVCC(多版本并发控制)而不是滚动提交日志。 GHC Haskell还具有非常优雅的STM monad,它也可以进行交易组合。 最后,为了稍微说一下我自己的号角,我最近为Scala实现了一个STM框架,该框架静态地强制执行引用限制。

所有这些都是有趣的实验,但似乎仅限于该领域(实验)。 所以我的问题是:你们中的任何人在现实世界中见过或使用过STM吗? 如果是这样,为什么? 它带来了什么好处? 性能如何? (在这一点上似乎有很多相互矛盾的信息)您将再次使用STM还是更喜欢使用其他并发抽象(例如actor)?

trans by 2019-10-09T19:19:24Z

ocaml-向Haskell添加ML样式模块的主要理论困难是什么?

众所周知,Haskell样式类型类和ML样式模块提供了用于指定接口的不同机制。 它们的功率(可能)是等效的,但实际上每个都有自己的优点和缺点。

由于在语言功能方面我有点包容性,所以我的问题是:在Haskell中添加ML样式模块的主要理论困难是什么? 我对以下几行的答案感兴趣:

  • 现有的哪些类型系统功能与ML样式模块之间的交互作用较弱? (不良互动的一个例子是GADT和功能依赖项,即使眼底技术在技术上等同于关联的类型!)

  • 为了编译ML样式的模块,必须在编译器端放弃什么?

  • ML样式模块如何与类型推断交互?

相关阅读:

  • 罗伯特·哈珀(Robert Harper)的帖子激起了这个问题
  • 关于Haskell Reddit的讨论
trans by 2019-10-08T02:29:33Z

如何在Haskell中以二进制或十六进制打印整数文字?

如何在Haskell中以二进制或十六进制打印整数文字?

printBinary 5 => "0101"

printHex 5 => "05"

哪些库/函数允许这样做?

我遇到了Numeric模块及其showIntAtBase函数,但是无法正确使用它。

> :t showIntAtBase 

showIntAtBase :: (Integral a) => a -> (Int -> Char) -> a -> String -> String
trans by 2019-10-07T19:14:44Z

haskell-具有Join()而不是Bind()的Monad

通常以returnfmap的顺序来解释Monad。但是,我认为您还可以按照>>=(和fmap)实现join

在缺乏一流功能的编程语言中,return的使用极为尴尬。 另一方面,fmap看起来很简单。

但是,我不确定我是否理解return的工作原理。 显然,它具有[Haskell]类型

join :: Monad m => m (m x) -> m x

对于清单monad,这是微不足道的,显然是return。但是对于一般monad,该方法实际上在做什么? 我看到了它对类型签名的作用,但是我试图弄清楚如何用Java或类似的语言编写类似的东西。

(实际上,这很容易:我不会。因为泛型已损坏。;-)但原则上问题仍然存在...)


哎呀。 似乎以前有人问过这个问题:

Monad加入功能

有人可以用returnfmapjoin勾画出普通monad的一些实现吗? (也就是说,根本没有提及>>=。)我认为这也许可以帮助它陷入我的愚蠢大脑中……

trans by 2019-10-07T10:39:39Z

关于类型安全性的Haskell类型与新类型

我知道newtype与Haskell中的type相比更常见,但是我从设计的角度而不是技术上的问题提出这种比较。

在命令式/ OO语言中,存在一种反模式“原始痴迷”,其中原始类型的大量使用降低了程序的类型安全性,并引入了相同类型值的意外互换性,否则它们打算用于不同目的。 例如,许多东西都可以是String,但是如果编译器可以静态地知道,这意味着我们是一个名称,并且意味着它是地址中的城市,那将是很好的。

那么,Haskell程序员多久使用一次newtype,以其他方式将类型区别赋予原始值? type的使用引入了别名,并为程序提供了更清晰易读的语义,但不能防止意外地互换值。 当我学习haskell时,我注意到类型系统与我遇到的任何系统一样强大。 因此,我认为这是自然而普遍的做法,但是从这个角度来看,我很少或没有对newtype的使用进行任何讨论。

当然,许多程序员的做事方式有所不同,但这在haskell中是否很常见?

trans by 2019-10-06T16:14:39Z

性能-Haskell为什么使用mergesort而不是quicksort?

在Wikibooks的Haskell中,有以下主张:

Data.List提供了用于对列表进行排序的排序功能。 它不使用快速排序; 相反,它使用称为mergesort的算法的有效实现。

Haskell在quicksort上使用mergesort的根本原因是什么? Quicksort通常具有更好的实用性能,但在这种情况下可能没有。 我认为,使用Haskell列表很难实现Quicksort的就地好处(不可能吗?)。

关于softwareengineering.SE,存在一个相关的问题,但实际上并不是关于为什么使用mergesort的问题。

我自己实现了这两种类型的概要分析。 Mergesort的性能优越(对于2 ^ 20个元素的列表,速度大约是它的两倍),但是我不确定quicksort的实现是否最佳。

编辑:这是我的mergesort和quicksort的实现:

mergesort :: Ord a => [a] -> [a]
mergesort [] = []
mergesort [x] = [x]
mergesort l = merge (mergesort left) (mergesort right)
    where size = div (length l) 2
          (left, right) = splitAt size l

merge :: Ord a => [a] -> [a] -> [a]
merge ls [] = ls
merge [] vs = vs
merge first@(l:ls) second@(v:vs)
    | l < v = l : merge ls second
    | otherwise = v : merge first vs

quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort [x] = [x]
quicksort l = quicksort less ++ pivot:(quicksort greater)
    where pivotIndex = div (length l) 2
          pivot = l !! pivotIndex
          [less, greater] = foldl addElem [[], []] $ enumerate l
          addElem [less, greater] (index, elem)
            | index == pivotIndex = [less, greater]
            | elem < pivot = [elem:less, greater]
            | otherwise = [less, elem:greater]

enumerate :: [a] -> [(Int, a)]
enumerate = zip [0..]

编辑2 3:要求我提供实现时间和Data.List.sort中的排序。按照@Will Ness的建议,我用-O2标志编译了要点,每次在main中更改提供的排序,并用+RTS -s执行。 排序后的列表是一个廉价创建的伪随机[Int]列表,其中包含2 ^ 20个元素。 结果如下:

  • Data.List.sort:0.171s
  • quicksort:1.092s(比Data.List.sort慢6倍)
  • quicksort:1.152s(比Data.List.sort慢7倍)
trans by 2019-10-06T02:16:33Z

测试-Haskell函数是否可以通过正确性属性进行证明/模型检查/验证?

继续以下思想:是否存在可证明的现实世界语言?

我不认识你,但是我讨厌写我不能保证的代码。

在问完上述问题并获得了惊人的答复之后(谢谢大家!),我决定缩小搜索范围,寻求一种可证明的,务实的Haskell方法。 我选择Haskell是因为它实际上很有用(有很多为此编写的Web框架,这似乎是一个不错的基准),而且我认为它在功能上足够严格,可以证明,或者至少可以测试不变式。

这就是我想要的(一直找不到)

我想要一个框架,可以查看用伪代码编写的Haskell函数:

add(a, b):
    return a + b

-并检查某些不变式是否保持在每个执行状态。 我希望获得一些正式的证明,但是我会选择模型检查器之类的东西。
在此示例中,不变的是给定值a和b,返回值始终是a + b之和。

这是一个简单的示例,但我认为这样的框架不可能存在。 可以测试的函数的复杂度肯定会有一个上限(一个函数的10个字符串输入肯定会花费很长时间!),但这会鼓励更仔细地设计函数,与使用其他形式函数没什么不同 方法。 想象一下使用Z或B,当您定义变量/集时,您一定要确保为变量提供尽可能小的范围。 如果您的INT永远不会超过100,请确保将其初始化! 我认为,像这样的技术以及适当的问题分解应该能够令人满意地检查像Haskell这样的纯功能语言。

我对形式方法或Haskell尚无经验。 让我知道我的想法是否合理,或者您认为haskell不适合? 如果您建议使用其他语言,请确保它通过了“具有网络框架”测试,并阅读原始问题:-)

trans by 2019-10-05T21:51:06Z

类型-Haskell中的()到底是什么?

我正在阅读Learn Has a Haskell,在monad章节中,对我来说,似乎()被视为每种类型的“空值”。 当我在GHCi中检查()的类型时,我得到

>> :t ()
() :: ()

这是一个非常令人困惑的声明。 看来()本身就是一种类型。 我对它如何适合该语言以及它如何能够代表任何类型感到困惑。

trans by 2019-10-05T07:55:25Z

haskell-最新GHC中不推荐使用的DatatypeContexts:为什么?

我只是在进行Haskell开发,并在新版本的GHC上重新编译了一些旧代码:

The Glorious Glasgow Haskell Compilation System, version 7.2.1

当我这样做时,我收到以下错误:

警告:-XDatatypeContexts已过时:普遍认为它不适合使用,已从Haskell语言中删除。

当您使用以下格式的代码时,将显示该消息:

data Ord a => MyType a
    = ConstructorOne a
    = ConstructorTwo a a

我的问题是:为什么首先不赞成使用此功能,我应该怎么做才能实现相同或相似的功能?

trans by 2019-10-05T01:00:01Z

haskell-暂停单子

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 ()))

yield monad是一种状态monad(因此具有明显的语义step)。 通常,像这样的monad具有某种“运行”功能,该功能运行计算并让您退回最终状态。 但是Pause是不同的:它提供了step函数,该函数运行计算直到调用神奇的yield函数。 在这里,计算被暂停,向调用者返回足够的信息,以便稍后继续计算。

要获得更大的威力,请执行以下操作:允许呼叫者修改yield呼叫之间的状态。 (例如,上面的类型签名应允许这样做。)


用例:编写执行复杂功能的代码通常很容易,但是使用一个完整的PITA对其进行转换以在其操作中也输出中间状态。 如果您希望用户能够在执行过程中进行某些更改,那么事情就会变得非常复杂。

实施思路:

  • 显然,可以使用线程,锁和yield来完成。但是我们可以做得更好吗? ;-)

  • 用连续单调疯狂吗?

  • 也许是某种作家monad,其中yield只是记录当前状态,然后我们可以通过遍历日志中的状态来“假装”为step。 (显然,这阻止了在步骤之间更改状态,因为我们现在并没有真正“暂停”任何内容。)

trans by 2019-10-05T00:17:47Z

列表-什么是Haskell的流融合

什么是Haskell的Stream Fusion,该如何使用?

trans by 2019-10-04T02:29:05Z

Scala和Haskell类型系统有哪些异同?

如何向Haskell专家解释Scala的类型系统?哪些示例显示了Scala的优势?

如何向高级Scala从业者解释Haskell的类型系统?在Haskell中可以做什么,而在Scala中不能做什么?

trans by 2019-10-03T18:48:22Z

haskell-使用MonadRef实施MonadCon

有一个众所周知的问题,我们不能在shift返回类型中使用reset类型。

但是,可以具有以下定义:

class Monad m => MonadCont' m where
    callCC' :: ((a -> forall b. m b) -> m a) -> m a
    shift :: (forall r.(a -> m r) -> m r) -> m a
    reset :: m a -> m a

然后找到一个有意义的实例。 在本文中,作者声称只要resetmzerom breset都可以在shift的基础上实现reset。但是我认为,如果确实有一个255320607419950707973,我们可以像下面这样实际实现callCC'

--satisfy law: mzero >>= f === mzero
class Monad m => MonadZero m where
    mzero :: m a

instance (MonadZero m, MonadRef r m) => MonadCont' m where
    callCC' k = do
        ref <- newRef Nothing
        v <- k (\a -> writeRef ref (Just a) >> mzero)
        r <- readRef ref
        return $ maybe v id r
    shift = ...
    reset = ...

(不幸的是,我对resetshift的语义不熟悉,因此我没有提供它们的实现)

对于我来说,此实现似乎还可以。 直观地,当调用reset时,我们将馈送shift,该函数自身的作用总是会失败(尽管我们无法提供reset的任意类型的值,但我们始终可以提供25532060741995199507972的mzero,并依法提供它) 应该有效地停止所有正在计算的进一步影响),并且它将接收到的值作为callCC'的最终结果。

所以我的问题是:

此实现是否对理想的reset起作用? 我们也可以使用适当的语义来实现shiftreset吗?

除上述内容外,我想知道:

为了确保适当的行为,我们必须假设reset具有某些属性。那么shift要遵循什么法律才能使上述实现达到预期效果?

UPDATE

事实证明,上述幼稚的实现还不够好。 为了满足“持续电流”

callCC $\k -> k m === callCC $ const m === m

我们必须将实施方式调整为

instance (MonadPlus m, MonadRef r m) => MonadCont' m where
    callCC' k = do 
       ref <- newRef mzero
       mplus (k $ \a -> writeRef ref (return a) >> mzero) (join (readRef ref))

换句话说,原始的reset是不够的,我们必须能够将shift值与常规计算组合在一起,而不会取消整个计算。

上面没有回答这个问题,只是在原始尝试被伪造为候选人的情况下进行了调整。 但是对于更新版本,原始问题仍然是问题。 特别是,resetshift仍然有待实施。

trans by 2019-10-03T16:39:09Z

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