无论我已经尝试使用map
,fmap
已工作过.为什么Haskell的创建者觉得需要一个map
函数?难道它不仅仅是目前已知的fmap
并且fmap
可以从语言中删除吗?
我喜欢在我的代码中为所有顶级定义添加类型签名.但是,实例声明中的类型签名似乎不被允许,如果我放置一个,我会从GHC获得"错位类型签名"错误.为什么会这样?为什么GHC不能检查类型签名是否与预期相同,如果不是,则拒绝(或警告)?
了解一下Haskell提到差异列表(在该页面上搜索该术语),其中列表l
不是直接表示而是作为函数表示(l++)
.这允许左右两侧更有效的连接.连接成为函数组合,最终可以转换为真实列表($[])
.我想知道哪些操作可以在差异列表上有效支持.例如,(:)
差异列表的等价物是
\x l -> (x:) . l
Run Code Online (Sandbox Code Playgroud)
可以有效地实施head
和tail
差异列表吗?这是明显的实现:
headTailDifList :: ([a] -> [a]) -> (a, [a] -> [a])
headTailDifList dl = (head l, ((tail l)++))
where
l = dl []
Run Code Online (Sandbox Code Playgroud)
对于真实列表,\l -> (head l, tail l)
以恒定时间运行.那怎么样headTailDifList
?也许由于懒惰的评估只会评估第一个元素l
?
headTailDifList
在固定时间内运行?还有一些其他的固定时间实现吗?这是一个候选人:
headTailDifList dl = (head (dl []), tail.dl )
Run Code Online (Sandbox Code Playgroud)
但是,如果dl
是id
(空差异列表),尾部不会抛出异常.
我有一个名为的数据类型Praat
.我想Praat
成为一个实例,Eq
以便两个Praat
s相等,当且仅当mx
它们相等时.怎么做到这一点?
-- data type
data Praat t = Praat [k] [(k,k,k,k)]
-- praat gives the maximum frequency
Praat t -> Int
mx (Praat [] _) = 0
mx (Praat (e:es) pt) = ...........
Run Code Online (Sandbox Code Playgroud)
这就是我试图定义实例但它无法正常工作的方式.
-- I want to make Praat instance of Eq so that two Praat are equal
-- when their respective `mx` are equal
instance Eq Praat where
mx :: (Praat k)->Int
(mx k) == (mx k) = …
Run Code Online (Sandbox Code Playgroud) 我想定义一个函数
invert :: [Int] -> [Int]
Run Code Online (Sandbox Code Playgroud)
假设其输入是一个排列[0..(n-1)]
,并返回其反转.可以使用列表和元组(没有数组)来定义它,以便它以线性时间运行吗?
这主要是出于学术兴趣; 在实际的代码我可能会使用Array
或STArray
或相似.
在Haskell中,let/where构造中的声明顺序无关紧要,例如:
f x = let g1 x y = if x>y then show x else g2 y x
g2 p q = g1 q p
in ...
Run Code Online (Sandbox Code Playgroud)
在声明之前g2
使用的地方g1
.但这不是Ocaml的情况:
# let a = b in
let b = 5 in
a;;
Warning 26: unused variable b.
Error: Unbound value b
Run Code Online (Sandbox Code Playgroud)
有没有理由说OCaml不像Haskell那样?在没有前瞻性声明的情况下,此功能对我来说似乎很有用.
是因为OCaml的严格评估,还是Haskell的懒惰?
考虑一个函数minout :: [Int] -> Int
,它接受一个不同的非负整数列表,并返回列表中不存在的最小非负整数.如果输入有重复,则函数的行为无关紧要.这可以在线性时间内实现,只使用列表(没有数组或向量或其他具有高效随机访问的数据结构)吗?
(这想出了这里.)
Befunge 的设计目标之一是难以编译。然而,它很容易解释。可以用传统语言编写解释器,比如 C。要将 Befunge 程序翻译成等效的机器代码,可以将 Befunge 代码硬编码到 C 解释器中,并将生成的 C 程序编译为机器代码。或者“编译”是否意味着排除这种翻译的更受限制的东西?
我有一个返回浮点列表的函数(mergeall).我想计算此列表中每对相邻元素的差异.例如:
[1.1,2.2,3.3,4.4,5.5,6.6]
do 1.1-2.2, 2.2-3.3,3.3-4.4...
return list of all difference
Run Code Online (Sandbox Code Playgroud)
所以,这应该传递到列表并返回一个列表.问题是:
这个功能的类型是 function :: Num a => ([Char],a) -> ([Char],a)
我对此函数的输入是类似的(".'*",0)
,函数通过添加200或400 的值来查找第一个'.'
或'*'
更新a
,a
具体取决于首先替换的字符.一旦更改了某些内容,字符列表的其余部分将附加到末尾(只更改了一个字符).如果未更改头部字符,则处理列表的其余部分,但保留头部字符.
我相信前两个保护语句是正确的,但我不知道如何使这个功能递归,以检查列表中的整个字符不变.
function ([], a) = ([], a)
function ((x:xs), a)
| x == '.' = ('-':xs, a+200)
| x =='*' = ('-':xs, a+400)
| otherwise = function(xs, a) --how do I put the unchanged x before xs without processing it?
Run Code Online (Sandbox Code Playgroud)
基本上,当函数到达时,我需要处理字符列表的其余部分,但是还需要返回未更改的字符.
所需输入输出的示例:
Main> function ("./-", 0)
("-/-",200)
Run Code Online (Sandbox Code Playgroud)
要么
Main> function ("-/-", 0)
("-/-",0)
Run Code Online (Sandbox Code Playgroud)
任何帮助是极大的赞赏!如果不清楚,我会澄清一下.我觉得我正在以错误的方式解决这个问题.
有没有办法删除3元素元组的第一个元素,所以我得到一个2元素元组而不必为此目的创建另一个函数?
(A,B,C) - >(B,C)
基本上我必须使用一个函数,它创建一个3元素元组然后我必须使用一个只使用它的最后两个元素的函数.
谢谢您的回答.