小编Chr*_*lor的帖子

滥用代数数据类型的代数 - 为什么这样做?

代数数据类型的"代数"表达式对于具有数学背景的人来说非常具有启发性.让我试着解释一下我的意思.

定义了基本类型

  • 产品
  • 联盟 +
  • 独生子 X
  • 单元 1

并使用简写X•X2XX+X等等,我们就可以定义如链表代数表达式

data List a = Nil | Cons a (List a)L = 1 + X • L

和二叉树:

data Tree a = Nil | Branch a (Tree a) (Tree a)T = 1 + X • T²

现在,我作为数学家的第一直觉是坚持这些表达方式,并试图解决LT.我可以通过重复替换来做到这一点,但似乎更容易滥用符号,并假装我可以随意重新排列.例如,对于链接列表:

L = 1 + X • L

(1 - X) • L = 1

L = 1 …

ocaml haskell functional-programming algebraic-data-types miranda

277
推荐指数
7
解决办法
1万
查看次数

存在类型的理论基础是什么?

哈斯克尔维基做了解释如何使用存在类型的一个很好的工作,但我不太神交背后的理论.

考虑这个存在类型的例子:

data S = forall a. Show a => S a      -- (1)
Run Code Online (Sandbox Code Playgroud)

为我们可以转换为的东西定义一个类型包装器String.维基提到我们真正想要定义的是类似的类型

data S = S (exists a. Show a => a)    -- (2)
Run Code Online (Sandbox Code Playgroud)

即一个真正的"存在主义"类型 - 松散地我认为这是"数据构造函数S采用Show实例存在并包装它的任何类型".事实上,你可能会写一个GADT如下:

data S where                          -- (3)
    S :: Show a => a -> S
Run Code Online (Sandbox Code Playgroud)

我没有尝试过编译,但似乎它应该可行.对我来说,GADT显然等同于我们想写的代码(2).

然而,对我来说,完全不明白为什么(1)等同于(2).为什么将数据构造函数移到外面forall变成了exists

我能想到的最接近的是De Morgan的逻辑定律,其中交换否定的顺序和量词将存在量词转换为通用量词,反之亦然:

¬(?x. px) ? ?x. ¬(px)
Run Code Online (Sandbox Code Playgroud)

但是数据构造函数似乎与否定运算符完全不同.

使用forall而不是不存在来定义存在类型的能力背后的理论是什么exists

haskell types type-systems existential-type quantifiers

66
推荐指数
3
解决办法
3716
查看次数

将MathJax与Jekyll一起使用

我有一个Jekyll博客,我想用它来使用MathJax,因为我希望能够输入类似的内容

$$\sum_{n=1}^\infty 1/n^2 = \frac{\pi^2}{6}$$
Run Code Online (Sandbox Code Playgroud)

在我的markdown文件中,并使用MathJax生成正确的LaTeX表达式,其方式与在math.stackexchange中完成的方式类似.

最简单的方法是什么?目前我在我的目录中有文件jsmath.js(GitHub gist),我想我可以mathjs在我的_includes目录中用一行命名一个简单的文件

<script src="path/to/jsmath.js></script>
Run Code Online (Sandbox Code Playgroud)

并在每个帖子中包括

{% include mathjs %}
Run Code Online (Sandbox Code Playgroud)

但这似乎不起作用 - 当我运行jekyll --server页面时生成,但没有任何内容可见.

我是以正确的方式来做这件事的吗?有没有更好的方法将MathJax与Jekyll一起使用?

jekyll mathjax

65
推荐指数
4
解决办法
2万
查看次数

集,函子和Eq混淆

最近关于集合的讨论出现了,在Scala中支持该zip方法以及如何导致bug,例如

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

我认为很明显Sets不应该支持一个zip操作,因为元素没有被排序.但是,有人认为这个问题Set不是真正的算子,也不应该有map方法.当然,你可以通过映射集合来解决自己的问题.现在切换到Haskell,

data AlwaysEqual a = Wrap { unWrap :: a }

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

instance Ord (AlwaysEqual a) where
    compare _ _ = EQ
Run Code Online (Sandbox Code Playgroud)

现在在ghci

ghci> import Data.Set as Set
ghci> let nums = Set.fromList [1, 2, 3]
ghci> Set.map unWrap $ Set.map …
Run Code Online (Sandbox Code Playgroud)

haskell scala equality functor

58
推荐指数
2
解决办法
3489
查看次数

为什么ocaml需要"let"和"let rec"?

可能重复:
为什么Ocaml/F#中的函数默认不递归?

OCaml用于let定义新函数,或let rec定义递归函数.为什么它需要这两者 - 我们不能只let用于一切吗?

例如,要在OCaml中定义非递归后继函数和递归因子(实际上,在OCaml解释器中)我可能会写

let succ n = n + 1;;

let rec fact n =
    if n = 0 then 1 else n * fact (n-1);;
Run Code Online (Sandbox Code Playgroud)

而在Haskell(GHCI)我可以写

let succ n = n + 1

let fact n =
    if n == 0 then 1 else n * fact (n-1)
Run Code Online (Sandbox Code Playgroud)

为什么OCaml区分letlet rec?这是一个性能问题,还是更微妙的东西?

recursion ocaml functional-programming

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

是否有一个被认为是"安全"的GHC扩展名单?

有时,如果没有至少一种语言扩展,我想写的一段代码是不合法的.当试图在研究论文中实现这些想法时尤其如此,这些论文倾向于使用在撰写论文时可用的任何spiffy,超扩展版本的GHC,而没有明确实际需要哪些扩展.

结果是我经常在我的.hs文件的顶部找到这样的东西:

{-# LANGUAGE TypeFamilies
           , MultiParamTypeClasses
           , FunctionalDependencies
           , FlexibleContexts
           , FlexibleInstances
           , UndecidableInstances
           , OverlappingInstances #-}
Run Code Online (Sandbox Code Playgroud)

我不介意,但我常常觉得我正在做出盲目的牺牲来安抚GHC的大神.它抱怨如果没有语言扩展X,某段代码无效,所以我为X添加了一个pragma.然后它要求我启用Y,所以我为Y添加了一个pragma.到这个结束时,我已经启用我不太了解的三个或四个语言扩展,我不知道哪些是"安全的".

用"安全"来解释我的意思:

  • 我明白这UndecidableInstances是安全的,因为虽然它可能导致编译器不终止,只要代码编译它就不会有意想不到的副作用.

  • 另一方面,OverlappingInstances显然是不安全的,因为它使我很容易意外地编写产生运行时错误的代码.

所以我的问题是:

是否有GHCextensions列表被认为是"安全的"并且"不安全"?

haskell ghc

36
推荐指数
1
解决办法
2097
查看次数

何时使用类型类,何时使用类型

几个月前,我正在重新审视我编写的用于组合搜索的一段代码,并注意到有一种替代的,更简单的方法可以做一些我之前用类型类实现的东西.

具体来说,我之前有一个搜索问题类型的类型类,它具有类型的状态,类型的s动作(状态操作)a,初始状态,获取(动作,状态)对列表的方式和测试状态是否为解决方案的方法:

class Problem p s a where
    initial   :: p s a -> s
    successor :: p s a -> s -> [(a,s)]
    goaltest  :: p s a -> s -> Bool
Run Code Online (Sandbox Code Playgroud)

这有点令人不满意,因为它需要MultiParameterTypeClass扩展,并且当你想要创建这个类的实例时,通常需要FlexibleInstances和可能的TypeSynonymInstances.它还会使您的功能签名变得混乱,例如

pathToSolution :: Problem p => p s a -> [(a,s)]
Run Code Online (Sandbox Code Playgroud)

我今天注意到我可以完全摆脱这个类,并使用类型代替,沿着以下几行

data Problem s a {
    initial   :: s,
    successor :: s -> [(a,s)],
    goaltest  :: s -> Bool
}
Run Code Online (Sandbox Code Playgroud)

这不需要任何扩展,功能签名看起来更好:

pathToSolution :: Problem s a -> [(a,s)]
Run Code Online (Sandbox Code Playgroud)

而且,最重要的是,我发现在重构我的代码以使用这个抽象而不是类型类之后,我留下了比以前少15-20%的行.

最大的胜利是在使用类型类创建抽象的代码中 …

haskell types typeclass

36
推荐指数
2
解决办法
2112
查看次数

与Haskell中常见的monad相对应的伴随函子对是什么?

在类别理论中,monad可以用两个伴随的仿函数构造.特别是,如果CD是类别而 F:C - > DG:D - > C是伴随函子,在某种意义上说是双射

hom(FX,Y)= hom(X,GY)

对于每个XÇÿd然后该组合物克邻FⅧ:C - "ç是一个单子.


一种这样的一对伴随函子可以通过固定式给出b,并采取FG

data F b a = F (a,b)
data G b a = G (b -> a)

instance Functor (F b) where
  fmap f (F (a,b)) = F (f a, b)

instance Functor (G b) where
  fmap f (G g) = G (f . …
Run Code Online (Sandbox Code Playgroud)

haskell category-theory

36
推荐指数
3
解决办法
1974
查看次数

在固定时间内尽可能多地计算列表

我想编写一个需要时间限制(以秒为单位)和列表的函数,并在时间限制内计算尽可能多的列表元素.

我的第一次尝试是首先编写以下函数,该函数计算纯计算并返回结果的时间:

import Control.DeepSeq
import System.CPUTime

type Time = Double

timed :: (NFData a) => a -> IO (a, Time)
timed x = do t1 <- getCPUTime
             r  <- return $!! x
             t2 <- getCPUTime
             let diff = fromIntegral (t2 - t1) / 10^12
             return (r, diff)
Run Code Online (Sandbox Code Playgroud)

然后,我可以根据这个定义我想要的功能:

timeLimited :: (NFData a) => Time -> [a] -> IO [a]
timeLimited remaining []     = return []
timeLimited remaining (x:xs) = if remaining < 0
    then return []
    else do
        (y,t) <- …
Run Code Online (Sandbox Code Playgroud)

time haskell timeout

26
推荐指数
1
解决办法
659
查看次数

Matlab中'end'的语义是什么?

通常使用end关键字作为访问或扩展Matlab中的数组的快捷方式,如

>> x = [1,2,3];
>> x(1:end-1)
ans =
    1   2
>> x(end+1) = 4
x =
    1   2   3   4
Run Code Online (Sandbox Code Playgroud)

但是,我惊讶地发现以下内容也有效

>> x(1:min(5, end))
ans =
    1   2   3   4
Run Code Online (Sandbox Code Playgroud)

我认为这end可能是一个特殊的形式,比如:,在索引操作中可以是特殊的,所以我创建了一个类来检测这个

classdef IndexDisplayer
  methods
    function subsref(self, s)
      disp(s);
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

您可以:在以下示例中看到特殊情况

>> a = IndexDisplayer;
>> a(1:3)
    type: '()'
    subs: {[1 2 3]}
>> a(:)
    type: '()'
    subs: {':'}
Run Code Online (Sandbox Code Playgroud)

但是,当我索引时,end我只是看到了

>> a(end)
    type: '()'
    subs: {[1]}
Run Code Online (Sandbox Code Playgroud)

这里end …

indexing matlab

26
推荐指数
1
解决办法
6263
查看次数