考虑面向对象的语言:
大多数人来自面向对象的编程背景,熟悉各种语言中常见且直观的界面,这些界面捕获了Java Collection
和List
界面的本质.Collection
"对象"是指不一定具有自然排序/索引的对象集合.A List
是具有自然排序/索引的集合.这些接口在Java中抽象了许多库数据结构,其他语言中的等效接口也是如此,并且需要对这些接口有深入的了解才能有效地与大多数库数据结构一起工作.
过渡到Haskell:
Haskell有一个类型级系统,它类似于对象上的接口作用于类型.当类型考虑功能时,Haskell似乎有一个关于Functors,Applicative,Monads等的设计良好的类型层次结构.他们显然想要正确且抽象良好的类型类.然而,当你看很多Haskell的容器(List
,Map
,Sequence
,Set
,Vector
)他们几乎都具有非常相似(或相同)的功能,但通过类型类不是抽象的.
一些例子:
null
用于测试"空虚"length
/size
用于元素计数elem
/member
用于设置包含empty
和/或 singleton
默认构造union
为集合联盟(\\)
/diff
用于设定差异(!)
/(!!)
用于不安全的索引(部分功能)(!?)
/lookup
用于安全索引(总功能)如果我想使用上面的任何函数,但是我已经导入了两个或更多个容器,我必须从导入的模块中开始隐藏函数,或者只从模块中显式导入必要的函数,或者限定导入的模块.但由于所有功能都提供相同的逻辑功能,因此它似乎很麻烦.如果函数是从类型类定义的,而不是在每个模块中单独定义的,那么编译器的类型推理机制可以解决这个问题.只要它们共享类型类,它也会使底层容器切换变得简单(即:让我们只使用一个Sequence
而不是List
更好的随机访问效率).
为什么Haskell没有Collection
和/或Indexable
类型类来统一和概括其中的一些功能?
我试图定义一个新的monad,我得到一个奇怪的错误
newmonad.hs
newtype Wrapped a = Wrap {unwrap :: a} instance Monad Wrapped where (>>=) (Wrap x) f = f x return x = Wrap x main = do putStrLn "yay"
$ ghc --version The Glorious Glasgow Haskell Compilation System, version 7.10.1 $ ghc newmonad.hs [1 of 1] Compiling Main ( newmonad.hs, newmonad.o ) newmonad.hs:2:10: No instance for (Applicative Wrapped) arising from the superclasses of an instance declaration In the instance declaration for ‘Monad Wrapped’
为什么我需要定义一个实例Applicative
?
我正在研究学校的时间复杂度,我们的主要关注点似乎是多项式时间 O(n^c)
算法和准线性时间 O(nlog(n))
算法,偶尔的指数时间 O(c^n)
算法作为运行时透视的一个例子.然而,从未涉及处理更大的时间复杂性.
我想看一个在阶乘时间内 运行的算法解决方案的示例问题O(n!)
.该算法可能是一种解决问题的简单方法,但不能人为膨胀以在因子时间运行.
如果因子时间算法是解决问题的最着名的算法,则额外的街道信誉.
使用Parsec 3.1
,可以解析几种类型的输入:
[Char]
同 Text.Parsec.String
Data.ByteString
同 Text.Parsec.ByteString
Data.ByteString.Lazy
同 Text.Parsec.ByteString.Lazy
我没有看到该Data.Text
模块的任何内容.我想解析Unicode内容而不会遇到String
效率低下的问题.所以我基于Text.Parsec.ByteString
模块创建了以下模块:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Text.Parsec.Text
( Parser, GenParser
) where
import Text.Parsec.Prim
import qualified Data.Text as T
instance (Monad m) => Stream T.Text m Char where
uncons = return . T.uncons
type Parser = Parsec T.Text ()
type GenParser t st = Parsec T.Text st
Run Code Online (Sandbox Code Playgroud)
附加评论:
我必须{-# LANGUAGE NoMonomorphismRestriction #-} …
我看过的许多Haskell教程几乎完全集中在语法上,而对如何构建程序的报道却很少.
例如...
这是C++应用程序的简要概述:
#include <iostream>
using namespace std;
int addition (int a, int b)
{
int r;
r=a+b;
return (r);
}
int main ()
{
int z;
z = addition (5,3);
cout << "The result is " << z;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我第一次开始学习C++时,这些例子极大地帮助我学习如何将各个部分组合成工作程序.也许我正在寻找错误的地方,但我找不到任何像Haskell那样直接和简单的例子.
我已经知道很多Haskell语法.我可以编写递归列表推导,并操纵字符串,整数和列出wazoo.
简而言之:我只想知道Haskell中两个子例程和变量传递是什么样的.如果我能够对如何构造Haskell程序有一些基本的了解,我可能最终能够将我学到的所有语法都用于某些用途.
我写了一个Haskell程序,它在列表上执行二进制搜索.至少这就是我的想法.当我用程序编译程序ghc v7.6.3
并运行程序时,我得到了以下输出:
progname: <<loop>>
Run Code Online (Sandbox Code Playgroud)
这个输出究竟意味着什么?这是否意味着我有一个无限循环ghc
优化了?我该怎么调试呢?
Haskell Typeclassopedia 3.2节的练习5要求在声明中提供证据或反例
两个Functors的组合也是一个Functor.
我一开始以为这是在讨论组合fmap
由两个单独的a实例定义的方法Functor
,但这并没有多大意义,因为就我所知,类型不会匹配.对于两种类型,f
并且f'
,类型fmap
将是fmap :: (a -> b) -> f a -> f b
和fmap :: (a -> b) -> f' a -> f' b
,并且实际上看起来并不可组合.那么组成两个是什么意思Functors
呢?
哈斯克尔支持一些基本的操作,通过列表递归,比如head
,tail
,init
和last
.我在内部想知道Haskell如何表示其列表数据?如果它是单链表,那么随着列表的增长init
,last
操作可能会变得昂贵.如果它是一个双向链表,那么所有四个操作都可以O(1)
很容易地完成,尽管会以一些内存为代价.无论哪种方式,对我来说都很重要,所以我可以编写适当的代码.(尽管,函数式编程的精神似乎是"问它是做什么,而不是它是怎么做的").
我想知道Functor
Haskell中的实例在多大程度上由函子定律(唯一)确定.
由于ghc
可以Functor
为至少"普通"数据类型派生实例,因此它们似乎必须至少在各种情况下都是唯一的.
为方便起见,Functor
定义和函子定律是:
class Functor f where
fmap :: (a -> b) -> f a -> f b
fmap id = id
fmap (g . h) = (fmap g) . (fmap h)
Run Code Online (Sandbox Code Playgroud)
问题:
可以map
从假设它是一个Functor
实例开始得出定义data List a = Nil | Cons a (List a)
吗?如果是这样,为了做到这一点,必须做出哪些假设?
是否有任何Haskell数据类型具有多个Functor
满足函子定律的实例?
什么时候可以ghc
派生出一个functor
实例而什么时候不能呢?
所有这些都取决于我们如何定义平等吗?该Functor
法律在价值的平等的条件下表达,但我们不要求Functors
有Eq
实例.那么这里有一些选择吗?
关于相等性,肯定存在一种我称之为"构造函数相等"的概念,它允许我们推断任何类型的任何值[a,a,a]
都"等于",即使它没有为它定义.所有其他(有用的)平等概念可能比这种等价关系更粗糙.但我怀疑法律中的平等更多是"推理平等"关系,并且可以是特定于应用的.有什么想法吗?[a,a,a]
a
a
(==)
Functor
在使用QuickCheck测试Monadic代码时(Claessen,Hughes 2002),assert
有类型:
assert :: (Monad m, Testable a) => a -> PropertyM m ()
Run Code Online (Sandbox Code Playgroud)
但是,在Test.QuickCheck.Monadic
,它有类型:
assert :: (Monad m) => Bool -> PropertyM m ()
Run Code Online (Sandbox Code Playgroud)
为什么assert
在库中有后一种类型?
haskell ×9
functor ×2
ghc ×2
abstraction ×1
algorithm ×1
compilation ×1
debugging ×1
factorial ×1
function ×1
list ×1
monads ×1
parsec ×1
quickcheck ×1
subroutine ×1
theory ×1
typeclass ×1