Questions tagged «haskell»

Haskell是一种功能性编程语言,具有强大的静态类型,惰性评估,广泛的并行性和并发支持以及独特的抽象功能。

7
具有Join()而不是Bind()的单子
Monad通常以return和交替解释bind。但是,我认为您也可以bind根据join(和fmap?)实现 在缺乏一流功能的编程语言中bind,使用起来非常尴尬。join另一方面,看起来很简单。 但是,我不确定我是否了解join工作原理。显然,它具有[Haskell]类型 加入:: Monad m => m(mx)-> mx 对于清单monad来说,这显然是微不足道的concat。但是对于一般的monad而言,此方法实际上在做什么?我看到了它对类型签名的作用,但是我试图弄清楚如何用Java或类似语言编写类似的内容。 (实际上,这很容易:我不会。因为泛型已损坏。;-)但从原理上讲,问题仍然存在...) 哎呀。似乎以前有人问过这个问题: Monad加入功能 可能有人勾画出使用普通的单子一些实现return,fmap和join?(也就是说,一点也不提>>=。)我认为这也许可以帮助它沉入我的愚蠢大脑中……
69 haskell  monads 

3
存在类型的理论基础是什么?
该哈斯克尔维基做了解释如何使用存在类型的一个很好的工作,但我不太神交背后的理论。 考虑以下存在类型的示例: data S = forall a. Show a => S a -- (1) 为我们可以转换为的东西定义类型包装String。维基提到我们真正想要定义的是类似 data S = S (exists a. Show a => a) -- (2) 即真正的“存在”类型-S大概我认为这是“数据构造函数接受Show实例存在的任何类型并将其包装”。实际上,您可能会编写如下的GADT: data S where -- (3) S :: Show a => a -> S 我没有尝试编译它,但是似乎它应该可以工作。对我来说,GADT显然等效于我们要编写的代码(2)。 但是,对我来说,为什么(1)等同于(2)并不清楚。为什么将数据构造函数移到外部会forall变成exists? 我能想到的最接近的是逻辑上的德摩根定律,在其中交换否定词和量词的顺序会将存在量词变成通用量词,反之亦然: ¬(∀x. px) ⇔ ∃x. ¬(px) 但是数据构造函数似乎与否定运算符完全不同。 …

6
暂停单子
Monad可以完成许多令人惊奇的疯狂事情。他们可以创建保存值叠加的变量。它们可以允许您在计算数据之前访问将来的数据。它们可以允许您编写破坏性的更新,但实际上不是。然后,延续monad可以让您大开眼界!通常是您自己的。;-) 但这是一个挑战:您可以制作一个可以暂停的单子吗? 数据暂停sx 实例Monad(Pause) 变异::(s-> s)->暂停s() 产量::暂停s() 步骤:: s->暂停s()->(s,也许(暂停s())) 该Pause单子是一种状态的单子(因此mutate,具有明显的语义)。通常,这样的monad具有某种“运行”功能,该功能运行计算并让您返回最终状态。但是Pause有所不同:它提供了一个step函数,该函数将运行计算直到调用魔术yield函数。在这里,计算被暂停,将足够的信息返回给调用者,以便以后恢复计算。 要获得更大的声望,请执行以下操作:允许呼叫者修改两次呼叫之间的状态step。(例如,上面的类型签名应允许这样做。) 用例:编写执行复杂功能的代码通常很容易,但是使用一个完整的PITA对其进行转换以在其操作中也输出中间状态。如果您希望用户能够在执行过程中进行某些更改,那么事情就会变得非常复杂。 实施思路: 显然,可以使用线程,锁和来完成IO。但是,我们可以做得更好吗?;-) 延续单子的疯狂吗? 也许是某种作家monad,它只yield记录当前状态,然后我们可以step通过遍历日志中的状态来“假装”它。(显然,这排除了在步骤之间更改状态的可能,因为我们现在并没有真正“暂停”任何内容。)

6
Haskell:非严格和懒惰有何区别?
我经常读到懒惰与非严格不一样,但是我很难理解它们之间的区别。它们似乎可以互换使用,但我知道它们具有不同的含义。我希望能帮助您理解其中的区别。 我对此帖子有一些疑问。我将在本文结尾总结这些问题。我有一些示例代码片段,我没有对其进行测试,仅将它们作为概念进行了介绍。我添加了报价,以免您查找报价。也许它将对以后的某个问题有所帮助。 非严格Def: 如果函数f在应用于非终止表达式时也未能终止,则称其为严格函数。换句话说,当f bot的值是|时,f是严格的。。对于大多数编程语言,所有功能都是严格的。但这在Haskell中并非如此。举一个简单的例子,考虑const1,常量1函数,其定义为: const1 x = 1 在Haskell中const1 bot的值是1。从操作上来说,由于const1不需要参数的值,因此它从不尝试对其求值,因此也不会陷入无限终止的计算中。因此,非严格函数也称为“惰性函数”,并说是“懒惰地”或“根据需要”评估其参数。 -一个温柔的介绍哈斯克尔:函数 我真的很喜欢这个定义。这似乎是我了解严格的最佳选择。是const1 x = 1懒惰的呢? 非严格意味着减少(评估的数学术语)从外部进入, 因此,如果您有(a +(b c)),则首先减小+,然后减小内部(b c)。 -哈斯克尔百科:懒惰与非严格 Haskell Wiki确实使我感到困惑。我了解他们在说什么订单,但是我看不到(a+(b*c))如果通过了,将如何严格地评估_|_? 在非严格评估中,不评估函数的参数,除非在函数主体的评估中实际使用了参数。 在教会编码下,运算符的惰性评估映射为功能的非严格评估;因此,非严格评估通常称为“惰性”。许多语言中的布尔表达式使用一种称为短路评估的非严格评估形式,在这种评估中,只要可以确定会产生明确的布尔值,评估就会立即返回,例如,在遇到真值的析取表达式中,或者遇到假的合取表达式,依此类推。条件表达式通常也使用惰性求值,即在得到明确的分支后立即返回求值。 -维基百科:评估策略 懒惰的Def: 另一方面,惰性求值意味着仅在需要表达式的结果时才对表达式求值(请注意从“归约”到“求值”的转变)。因此,当评估引擎看到一个表达式时,它将构建一个thunk数据结构,其中包含评估该表达式所需的任何值以及指向该表达式本身的指针。当实际需要结果时,评估引擎将调用该表达式,然后将结果替换为thunk以供将来参考。... 显然,一个笨拙的表情和一个部分评估的表情之间有很强的对应关系。因此,在大多数情况下,术语“惰性”和“非严格”是同义词。但不完全是。 -哈斯克尔百科:懒惰与非严格 这似乎是Haskell的特定答案。我认为懒惰意味着沉重,非严格意味着部分评估。比较是否简化了?不懒总是意味着的thunk和非严格总是意味着部分评价。 在编程语言理论中,惰性评估或按需调用1是一种评估策略,它会延迟对表达式的评估,直到实际需要其值为止(非严格评估),并且还避免了重复评估(共享)。 -维基百科:懒惰的评估 势在必行的例子 我知道大多数人在学习功能语言时都会说忘记命令式编程。但是,我想知道这些是否属于非严格,懒惰,或者两者兼有?至少它会提供一些熟悉的东西。 短路 f1() || f2() C#,Python和其他具有“ yield”功能的语言 public static IEnumerable Power(int number, int exponent) { …


5
被“替代”类型类的含义及其与其他类型类的关系所迷惑
我一直在学习Typeclassopedia来学习类型类。我一直无法理解Alternative(并且MonadPlus,对此)。 我遇到的问题: 'pedia说:“ Alternate类型类适用于也具有类半体结构的Applicative函数。” 我不明白这一点-“替代”是否意味着与Monoid完全不同?也就是说,我理解Alternative类型类的要点是在两件事之间进行选择,而我将Monoids理解为要结合事物。 为什么Alternative需要一个empty方法/成员?我可能是错的,但似乎根本没有使用它……至少在我能找到的代码中。而且这似乎与课程的主题不符-如果我有两件事,并且需要选择其中一件事,我需要做什么? 为什么Alternative类型类需要一个Applicative约束,为什么它需要一种* -> *?为什么不只是拥有<|> :: a -> a -> a?所有实例仍然可以以相同的方式实现...我认为(不确定)。Monoid不提供什么值? 什么是点MonadPlus式类?我不能仅通过同时使用aMonad和a来释放其所有优点Alternative吗?为什么不干掉它呢?(我确定我错了,但是我没有任何反例) 希望所有这些问题都是连贯的……! 赏金更新:@Antal的答案是一个不错的开始,但是Q3仍然是公开的:Alternative提供了Monoid没有提供什么?我发现此答案不尽人意,因为它缺少具体的示例,并且对另类的更高种类如何将其与Monoid进行了具体讨论。 如果要将应用程序的效果与Monoid的行为结合起来,为什么不做: liftA2 mappend 这让我更加困惑,因为许多Monoid实例与Alternative实例完全相同。 这就是为什么我要寻找一些特定的示例,这些示例说明了为什么需要“替代”,以及与Monoid有何不同(或意味着不同)。

3
函数编程中的“部分功能”到底是什么意思?
根据我的理解,部分函数是通过向函数传递比预期少的参数而获得的函数。例如,如果这在Python中直接有效: >>> def add(x,y): ... return x+y ... >>> new_function = add(1) >>> new_function(2) 3 在上面的代码段中,new_function是部分功能。但是,根据Haskell Wiki,部分函数的定义为 局部函数是未针对指定类型的所有可能参数定义的函数。 因此,我的问题是:“部分函数”到底是什么意思?

2
处理递归和类型时如何减少代码重复
我目前正在为一种编程语言开发一个简单的解释器,并且我的数据类型如下: data Expr = Variable String | Number Int | Add [Expr] | Sub Expr Expr 我有许多函数可以执行简单的操作,例如: -- Substitute a value for a variable substituteName :: String -> Int -> Expr -> Expr substituteName name newValue = go where go (Variable x) | x == name = Number newValue go …

5
有没有机会写“ C major”而不是“ major C”?
我在音乐项目中遇到了一个美学上的小问题,并且困扰了我一段时间。 我有一个类型data Key = C | D | ...,可以Scale从Key和构造一个Mode。该Mode例如主要的和次要的规模进行了区分。 我可以将Mode类型定义为从Keyto 的函数Scale。在这种情况下,模式将使用小写名称(可以),我可以得到一个这样的Scale aScale = major C 但是音乐家不会这样说话。他们将此比例称为C大尺度,而不是C大尺度。 我想要的是 理想情况下,我想写 aScale = C major 这有可能吗? 我尝试了什么 我可以创建Key一个Scale从构造a的函数Mode,所以我可以写 aScale = c Major 但是我不能将关键限制在构建音阶上。其他事物也需要它们(例如,构建和弦)。也Key应该是的实例Show。 当我使用额外的函数(或值构造函数)时,可以放在Mode后面Key: aScale = scale C major 与 scale :: Key -> Mode -> Scale 但是额外的单词标度看起来很吵,并且与名称相反,它scale实际上与标度无关。聪明的地方在于major,scale确实是公正flip ($)。 使用a newtype Mode = …
39 haskell  dsl 

3
为什么在Haskell中不将访问System.Info视为IO操作?
在模块中,System.Info我看到以下功能: os :: String arch :: String compilerName :: String compilerVersion :: Version 为什么没有IO那里?他们正在访问系统...我错了吗?我的期望是: os :: IO String arch :: IO String compilerName :: IO String compilerVersion :: IO Version 用例: print os -- "darwin" print arch -- "x86_64" print compilerName -- "ghc"
25 haskell 

2
现代GHC版本是否具有某种形式的证明擦除?
假设我有一个仅出于类型系统的利益而存在的参数,例如在此小程序中: {-# LANGUAGE GADTs #-} module Main where import Data.Proxy import Data.List data MyPoly where MyConstr :: Proxy a -> a -> (Proxy a -> a -> Int -> Int) -> MyPoly listOfPolys :: [MyPoly] listOfPolys = [MyConstr Proxy 5 (const (+)) , MyConstr Proxy 10 (const (+)) , MyConstr …

2
对纯净性的需求
我正在学习Haskell的Applicatives。在我看来(我可能错了),pure实际上并不需要该功能,例如: pure (+) <*> [1,2,3] <*> [3,4,5] 可以写成 (+) <$> [1,2,3] <*> [3,4,5] 有人可以解释该pure函数提供的显式映射所带来的好处fmap吗?

2
推导这种类型时,“了解Haskell”中的假设是什么?
这个问题不是主观的。参考书中使用了一个非常具体的动词,我想了解该措词的含义,因为恐怕我误会了某些东西。 从“ 了解您的Haskell”中,以下段落是包含“我们假设*” 的第三段也是最后一段。 data Barry t k p = Barry { yabba :: p, dabba :: t k } 现在我们要使其成为的实例Functor。Functor想要那种类型,* -> *但Barry看起来不像那种类型。是什么样的Barry?好吧,我们看到它需要三个类型参数,因此它将是something -> something -> something -> *。可以肯定地说这p是一种具体类型,因此具有一种*。因为k,我们假设*等等,t因此具有一种* -> *。现在,让something我们用用作占位符的替换这些类型,我们看到它有一种(* -> *) -> * -> * -> *。 我们为什么要承担一切呢?读完“我们假设X(即我们假设X为真)”后,我自然认为我们也应该考虑X为假的情况。在这个例子中的具体情况,不能t是那种(* -> *) -> *和k那种(* -> *)?如果是这样,无论是什么t,k实际上是什么,t k仍将是一个具体类型,不是吗? 我看到整个推理过程随后都针对编译器进行了检查,但我认为编译器不假定。如果可以,我想知道,如果不知道,恐怕会丢失该段的含义。
18 haskell 


2
Haskell:Typeclass与传递函数
在我看来,您总是可以传递函数参数,而不是使用类型类。例如,而不是定义相等类型类: class Eq a where (==) :: a -> a -> Bool 并在其他函数中使用它来指示类型实参必须是的实例Eq: elem :: (Eq a) => a -> [a] -> Bool 我们是否elem可以不使用类型类就定义函数,而是传递可以完成工作的函数参数?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.