天道酬勤,学无止境

haskell

Weak head normal form and normal form

问题 我对弱头范式和范式有疑问。 弱头范式意味着,表达式只会在需要到达数据构造函数时进行评估。 正常形式意味着,表达式将被完全评估。 现在,我有以下表达: \x -> x * 10 为什么上面的表达式是正常形式的? "Papu" ++ "chon" 为什么上面的表达式既不在 WHNF 也不在 NF 中? 回答1 WHNF 计算的距离足以到达数据构造函数或 lambda 函数。 如果您有一个尚未使用参数调用的 lambda 函数,则无论如何您都无法进一步评估它。 因此 lambda 函数在 WHNF 中,实际上在 NF 中,因为没有什么可以进一步评估的了。 现在,如果您使用参数调用lambda 函数,我们可以评估结果可能是什么。 但是 lambda 函数本身呢? 没有什么可做的了。 您的第一个表达式是一个没有参数的 lambda 函数。 因此它是正常形式的。 您的第二个表达式既不是数据构造函数也不是 lambda,因此不是任何正常形式。 现在,如果您对它进行一步评估,您将获得 'P' : ("apu" ++ "chon") 哪个(尽管语法看起来不像)以数据构造函数(即(:) )开头,因此在 WHNF 中,但不在NF 中(因为它仍然包含未计算的(++)子表达式)。 如果我们摆脱中缀语法,也许会更容易: (++) "Papu" "chon" 对比 (:) 'P' ( (++) "apu"

2022-05-17 03:50:08    分类:技术分享    haskell

architecture x86_64 while running Haskell code, Haskell OSX iconv

问题 $ ghc --make BoardMain.hs Linking BoardMain ... Undefined symbols for architecture x86_64: "_iconv", referenced from: _hs_iconv in libHSbase-4.9.1.0.a(iconv.o) (maybe you meant: _hs_iconv, _base_GHCziIOziEncodingziIconv_iconvEncoding5_closure , _base_GHCziIOziEncodingziIconv_iconvEncodingzuloc_info , _base_GHCziIOziEncodingziIconv_iconvEncoding9_info , _hs_iconv_open , _base_GHCziIOziEncodingziIconv_iconvEncoding10_closure , _base_GHCziIOziEncodingziIconv_iconvEncoding11_info , _base_GHCziIOziEncodingziIconv_iconvEncoding7_closure , _base_GHCziIOziEncodingziIconv_iconvEncoding8_info , _base

2022-05-16 16:17:22    分类:技术分享    haskell

GLUT Error in Haskell Program

问题 我正在使用带有 Haskell 的 OpenGL。 我尝试了一个示例程序,它使用 ghc Compiler 成功编译,但是当我运行它时,出现此错误 用户错误(未知的 GLUT 条目 glutInit) 我对此进行了搜索,但大多数答案都与此问题有关,即 mac OS X 和 Windows。 但是我在 Ubuntu 15 上遇到了这个错误。 这个问题以前被问过,但与windows有关 下面是我使用的示例程序。 import Graphics.Rendering.OpenGL import Graphics.UI.GLUT main :: IO () main = do (_progName, _args) <- getArgsAndInitialize _window <- createWindow "Hello World" displayCallback $= display mainLoop display :: IO () display = do clear [ ColorBuffer ] 回答1 sudo apt-get install freeglut3

2022-05-16 16:00:25    分类:技术分享    haskell   opengl   glut   freeglut

FromJSON instance with DataKinds

问题 尝试使用 TypeLits 对数据类型进行 JSON 反序列化,但遇到以下问题: Couldn't match type ‘n’ with ‘2’ ‘n’ is a rigid type variable bound by the instance declaration at test.hs:14:10 Expected type: aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser (X n) Actual type: aeson-0.11.2.1:Data.Aeson.Types.Internal.Parser (X 2) 在以下示例中,在FromJSON实例中一般允许Nat的正确语法如何: {-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} import GHC.TypeLits import Data.Aeson import Control.Monad (mzero) data X (n :: Nat) where A :: Integer -> X 1 B :: Integer -> X 2 instance FromJSON (X n)

2022-05-15 17:40:32    分类:技术分享    haskell   aeson   data-kinds

Why doesn't this Haskell code exhaust the heap?

问题 此代码汇总了在顶层指定的两个(相互取消的)无限列表的内容: {-# language BangPatterns #-} module Main where unending1 :: [Int] unending1 = cycle [1] unending2 :: [Int] unending2 = cycle [negate 1] main :: IO () main = do let summator :: Int -> [Int] -> [Int] -> Int summator !acc (i1 : rest1) (i2 : rest2) = if acc > 100 then acc -- never happens else summator (acc+i1+i2) rest1 rest2 print (summator 0 unending1 unending2) 我编译这段代码时没有优化和低堆大小,如下所示: ghc -O0 -with-rtsopts="-M10m" Main.hs 我的直觉是这段代码会导致内存泄漏,因为求和函数会尝试“物化”这两个列表,并且它们的头部都在顶层,因此它们不会被丢弃。 但是,当我执行程序时,它似乎无限期地运行而没有问题。 我错在哪里? 编辑。 使用-ddump-simpl检查生成的核心,列表似乎保持在顶层。 例如: Result

2022-05-15 12:20:09    分类:技术分享    haskell   memory-leaks

Limit a number to a range (Haskell)

问题 我公开了一个带有两个参数的函数,一个是最小界限,另一个是最大界限。 如何使用类型确保例如最小界限不大于最大界限? 我想避免创建一个智能构造函数并返回一个 Maybe,因为它会使整个使用变得更加麻烦。 谢谢 回答1 这并不能完全回答您的问题,但有时有效的一种方法是改变您对类型的解释。 例如,而不是 data Range = {lo :: Integer, hi :: Integer} 你可以使用 data Range = {lo :: Integer, size :: Natural} 这样,就无法表示无效范围。 回答2 此解决方案使用依赖类型(并且可能过于重量级,请检查dfeuer的答案是否足以满足您的需求)。 该解决方案利用了base中的GHC.TypeLits模块,以及 typelits-witnesses 包。 这是一个差分函数,它接受两个整数参数(静态已知)并在第一个数字大于第二个数字时在编译时报错: {-# language TypeFamilies #-} {-# language TypeOperators #-} {-# language DataKinds #-} {-# language ScopedTypeVariables #-} import GHC.TypeLits import GHC.TypeLits.Compare import Data

2022-05-15 07:07:04    分类:技术分享    haskell   types   functional-programming   type-theory   hindley-milner

ghci randomio type inference

问题 GHCi> :m System.Random GHCi> :t randomIO randomIO :: Random a => IO a GHCi> randomIO -1557093684 GHCi> randomIO 1342278538 回答1 我想这只是简单的单态限制。 如果未指定实际类型,则Num a => a等多态类型将像Integer一样处理。 可能这条规则也适用于ghci ,你会看到整数类型而不是一些未知类型的变量。 UPD 1:实际上是用户指南这部分关于默认规则的真正答案。 UPD 2: Random类型类的案例变得比我预期的要困难。 因此,在这种情况下,由于报告中提到的default (Integer, Double)声明而解决了默认规则。 考虑下一个 ghci 会话 Prelude System.Random> default () Prelude System.Random> randomIO <interactive>:6:1: No instance for (Show (IO a0)) arising from a use of ‘print’ In a stmt of an interactive GHCi command: print it Prelude System.Random> default (Integer) Prelude

2022-05-14 22:09:10    分类:技术分享    haskell   ghci

How do you save a file using Conduit?

问题 如何使用导管的库保存文件? 我浏览了导管的教程,但似乎找不到任何东西,这是我的用例: main :: IO () main = do xxs <- lines <$> (readFile filePath) sourceList xxs =$ pipe $$ saveFile pipe :: Monad m => Conduit String m String pipe = undefined 所以这里有两个问题: 使用lines字符串转换为字符串列表然后将其提供给sourceList是否有意义? 我应该如何实现saveFile函数,以便在字符串xxs被完全处理后,我可以将其写入磁盘? 回答1 您尝试使用conduit库执行的操作的一个小示例: #!/usr/bin/env stack {- stack --resolver lts-6.7 --install-ghc runghc --package conduit-extra --package resourcet --package conduit -} import Data.Conduit.Binary (sinkFile, sourceFile) import Control.Monad.Trans.Resource import Data.Conduit (($$), await, Conduit, (=$)

2022-05-14 18:37:37    分类:技术分享    haskell   conduit   haskell-pipes

The meaning of <= vs. => in Haskell

问题 回答1 两者完全无关; 它们只是因为 ASCII 而显得相关。 如果您查看它们的 Unicode 等效项,则更有意义: =>是一个箭头: ⇒ 。 它用于在类型签名中指定约束: Eq a => a -> a -> Bool 上述签名中的Eq a =>意味着类型变量a可以是作为Eq类的实例的任何类型。 也就是说,任何具有deriving (Eq)或显式实例(如instance Eq Type where ... )的类型。 在函数签名中, ->指定一个普通参数,而=>指定签名中的约束。 在上面的示例中( Eq a => a -> a -> Bool ),该函数接受两个 a 类型a参数并给我们一个Bool 。 Eq a =>部分不是函数的显式参数; 它只是告诉我们a必须是Eq的一部分(也就是说,它必须与==可比较)。 <=小于或等于。 也就是说,它是≤ ,而不是⇐ 。 这是标准库中的一个普通函数,它是Ord类的一部分: λ> :t (<=) (<=) :: Ord a => a -> a -> Bool 您可以在正常表达式中使用它: λ> 10 <= 12 True 它们看起来对称的唯一原因是因为≤和⇐的 ASCII 近似值是相同的,但这只是符号的限制。 否则,它们是完全无关的。 您可以在代码中使用明确的 Unicode 符号。 UnicodeSyntax扩展允许使用⇒ for =

2022-05-14 07:17:04    分类:技术分享    haskell

Haskell type inference for lambda functions (in map) [duplicate]

问题 这个问题在这里已经有了答案: 什么是单态限制? (1 个回答) 5年前关闭。 示例 1 以下没有类型声明的定义将引发错误: f :: Eq t => (t,t) -> Bool -- omiting this line will result in an error f = \(x,y) -> x==y (我知道这个函数可以写得更短,但这不是重点。) 示例 2 另一方面,在使用map的函数中使用相同的 lambda 函数确实可以工作而不会产生错误: g l = map (\(x,y) -> x==y) l (仅作为说明: g [(3,4),(5,5),(7,6)]将产生[False,True,False] 示例 3 以下代码也非常好,它似乎与上面的原始f完全相同。 在这里,类型推断似乎有效。 f' (x,y) = x==y 问题 所以我的问题是:为什么我们在第一种情况下需要类型声明,而在第二种和第三种情况下不需要? 回答1 如果您使用: {-# LANGUAGE NoMonomorphismRestriction #-} f = \(x,y) -> x==y 你不会得到错误。 更新 Haskell Wiki page on Monomorphism Restriction (link) 提供了一些关于为什么这些定义被区别对待的细节: f1 x = show x f2 = \x

2022-05-13 22:36:19    分类:技术分享    haskell   lambda   type-inference