Function `(整数a)=>;a->;Bool`和'Integer->;布尔?
今天我在Haskell写了我的第一个程序。由于它不是一个典型的“Hello World”节目,它实际上做的远不止这些,所以请祝贺我:D 无论如何,我对我的代码和Haskell中的语法没有什么疑问 问题: 我的程序从标准输入读取一个整数Function `(整数a)=>;a->;Bool`和'Integer->;布尔?,function,haskell,purely-functional,Function,Haskell,Purely Functional,今天我在Haskell写了我的第一个程序。由于它不是一个典型的“Hello World”节目,它实际上做的远不止这些,所以请祝贺我:D 无论如何,我对我的代码和Haskell中的语法没有什么疑问 问题: 我的程序从标准输入读取一个整数N,然后,对于[1,N]范围内的每个整数i,它会打印i是否为素数。当前未检查输入错误。:-) 解决方案:(还有疑问/问题) 为了解决这个问题,我编写了这个函数来测试整数的素性: is_prime :: Integer -> Bool is_prime n =
N
,然后,对于[1,N]
范围内的每个整数i
,它会打印i
是否为素数。当前未检查输入错误。:-)
解决方案:(还有疑问/问题)
为了解决这个问题,我编写了这个函数来测试整数的素性:
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
根据(顺便说一句,这是一个写得很好的教程),第一行应该是:(教程说(整数a)=>a->String
,所以我认为(整数a)=>a->Bool
也应该可以。)
这不起作用,并给出了上述公布的错误(?)
为什么它不起作用?这条线(不起作用)和这条线(起作用)有什么区别
另外,通过
1
循环到N
的惯用方法是什么?我对代码中的循环并不完全满意。请提出改进建议。这是我的密码:
--read_int function
read_int :: IO Integer
read_int = do
line <- getLine
readIO line
--is_prime function
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
main = do
n <- read_int
dump 1 n
where
dump i x = do
putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
if i >= x
then putStrLn ("")
else do
dump (i+1) x
——读取int函数
read_int::IO整数
read_int=do
线布尔
is_素数n=helper n2
哪里
helper::Integer->Integer->Bool
助手n i
|n<2*i=True
|模n i>0=辅助对象n(i+1)
|否则=假
main=do
n=x
然后putStrLn(“”)
否则会
转储(i+1)x
整数a
,而不是整数a
。看map
和friends是您在Haskell中循环的方式。以下是我将如何重新编写循环:
main :: IO ()
main = do
n <- read_int
mapM_ tell_prime [1..n]
where tell_prime i = putStrLn (show i ++ " is a prime? " ++ show (is_prime i))
main::IO()
main=do
n第1部分:如果您再次阅读本教程,您会注意到它实际上以以下形式给出了类型签名:
isPrime :: Integer -> Bool
-- or
isPrime :: Integral a => a -> Bool
isPrime :: (Integral a) => a -> Bool -- equivalent
这里,Integer
是一个具体类型的名称(具有实际表示形式),而Integral
是一类类型的名称。Integer
类型是Integral
类的成员
约束Integral a
意味着无论a
是什么类型,a
都必须是Integral
类的成员
第2部分:有很多方法可以编写这样的函数。您的递归定义看起来不错(尽管您可能希望使用n
而不是n<2*i
,因为它更快)
如果您正在学习Haskell,您可能想尝试使用高阶函数或列表理解编写它。比如:
module Main (main) where
import Control.Monad (forM_)
isPrime :: Integer -> Bool
isPrime n = all (\i -> (n `rem` i) /= 0) $ takeWhile (\i -> i^2 <= n) [2..]
main :: IO ()
main = do n <- readLn
forM_ [1..n] $ \i ->
putStrLn (show (i) ++ " is a prime? " ++ show (isPrime i))
主模块(Main),其中
导入控制.Monad(表单)
iPrime::Integer->Bool
iPrime n=all(\i->(n`rem`i)/=0)$takeWhile(\i->i^2您误读了教程。它会说类型签名应该是
is_prime :: (Integral a) => a -> Bool
-- NOT Integer a
这些是不同的类型:
Integer->Bool
- 这是一个函数,它接受类型为
Integer
的值,并返回类型为Bool
的值
Integral a=>a->Bool
- 这是一个函数,它接受
a
类型的值并返回Bool
类型的值
- 什么是
a
?它可以是调用方选择的实现Integral
类型类的任何类型,例如Integer
或Int
(还有Int
和Integer
之间的区别?后者可以表示任意大小的整数,前者最终会卷起,类似于C/Java/etc中的Int
s。)
循环的惯用方式取决于循环的功能:它可以是映射、折叠或过滤器
您在main
中的循环是一个映射,因为您在循环中执行i/o,所以需要使用mapM\uu
let dump i = putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
in mapM_ dump [1..n]
同时,中的循环是_prime
是一个折叠(在本例中,具体地说是all
):
(在风格上,Haskell习惯使用isPrime
等名称,而不是is_prime
等名称)你的意思是Integral a
?@Heatsink:不。我甚至不知道Integral
是否存在。是吗?它应该是Integral
?它可能应该是Integral
。另外,你的两个超链接指向同一个URL,这是故意的吗?@Heatsink:超链接被更正了。只是一些不严格相关的事情注意到您遇到的问题:Haskell中的函数应用程序只是并置的,所以show(i)
=show i
,putStrLn(“”)
=putStrLn”“
;主要的命名约定是camelCase(基本上所有库都使用它)而且read\u int
已经在Prelude
中,名字是readLn
@Vitus:Ohh我需要导入它。我还没有遇到import
。顺便问一下,这个语法\I->(n`rem`I)/=0
是什么意思?\I->
引入了一个带一个参数的匿名函数(功能体内部命名为i
).n`rem`i
只是另一种编写rem ni
的方法。你可以将任何函数用倒勾括起来,将其转换为中缀运算符。@Vitus:这个匿名函数更像是lambda,它捕获局部变量,比如n
,对吗?基本上就像你在where
中声明了一个局部函数一样是的,它捕获了它的上下文,也就是所有的自由变量。吹毛求疵:互质
是一个误导性的名称。事实证明,它实际上只为i
调用,结果是
is_prime :: (Integral a) => a -> Bool
-- NOT Integer a
let dump i = putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
in mapM_ dump [1..n]
is_prime :: Integer -> Bool
is_prime n = all nondivisor [2 .. n `div` 2]
where
nondivisor :: Integer -> Bool
nondivisor i = mod n i > 0