Function `(整数a)=>;a->;Bool`和'Integer->;布尔?

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 =

今天我在Haskell写了我的第一个程序。由于它不是一个典型的“Hello World”节目,它实际上做的远不止这些,所以请祝贺我:D

无论如何,我对我的代码和Haskell中的语法没有什么疑问

问题:

我的程序从标准输入读取一个整数
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