{"id":22225515,"url":"https://github.com/beliavsky/haskell_and_fortran","last_synced_at":"2025-03-25T08:22:11.825Z","repository":{"id":181617899,"uuid":"667045995","full_name":"Beliavsky/Haskell_and_Fortran","owner":"Beliavsky","description":"Haskell and Fortran programs to solve the same problems","archived":false,"fork":false,"pushed_at":"2023-07-22T00:56:19.000Z","size":70,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-30T07:42:42.690Z","etag":null,"topics":["fortran","haskell"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Beliavsky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-16T13:13:56.000Z","updated_at":"2023-07-17T11:55:01.000Z","dependencies_parsed_at":"2025-01-30T07:41:29.847Z","dependency_job_id":"37a95bbf-989d-4608-a4a0-7f4c4728d96e","html_url":"https://github.com/Beliavsky/Haskell_and_Fortran","commit_stats":null,"previous_names":["beliavsky/haskell_and_fortran"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Beliavsky%2FHaskell_and_Fortran","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Beliavsky%2FHaskell_and_Fortran/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Beliavsky%2FHaskell_and_Fortran/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Beliavsky%2FHaskell_and_Fortran/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Beliavsky","download_url":"https://codeload.github.com/Beliavsky/Haskell_and_Fortran/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245423913,"owners_count":20612865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fortran","haskell"],"created_at":"2024-12-03T00:18:15.484Z","updated_at":"2025-03-25T08:22:11.802Z","avatar_url":"https://github.com/Beliavsky.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Haskell and Fortran\nHere are Haskell and Fortran programs to solve the same problems, which I am writing to learn Haskell. The Glasgow Haskell Compiler and gfortran are used.\n\n**Compute the primes below 50, using the Sieve of Eratosthenes and excluding even numbers above 2 and considering only factors up to sqrt(n).**\n\n**Haskell**\n\n```Haskell\nprimesBelowN :: Int -\u003e [Int]\nprimesBelowN n = 2 : [i | i \u003c- [3,5..n], isPrime i]\n\nisPrime :: Int -\u003e Bool\nisPrime n = not $ hasFactor 2 (floor.sqrt.fromIntegral $ n) n\n\nhasFactor :: Int -\u003e Int -\u003e Int -\u003e Bool\nhasFactor f t n\n  | f \u003e t = False\n  | n `mod` f == 0 = True\n  | otherwise = hasFactor (f+1) t n\n\nmain :: IO ()\nmain = print $ primesBelowN 50\n```\n\noutput: \n`[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]`\n\n**Fortran**\n\n```Fortran\nmodule m\nimplicit none\ncontains\nelemental logical function is_prime(n)\n  integer, intent(in) :: n\n  integer :: i\n  is_prime = .false.\n  do i = 2, int(sqrt(real(n)))\n     if (mod(n, i) == 0) return\n  end do\n  is_prime = .true.\nend function is_prime\n\nfunction primes_below(n) result(pvec)\n  integer, intent(in) :: n\n  integer, allocatable :: pvec(:)\n  integer :: i\n  pvec = [2, (i, i=3,n,2)]\n  pvec = pack(pvec, is_prime(pvec))\nend function primes_below\nend module m\n\nprogram main\n  use m\n  implicit none\n  print \"(*(i0,:,','))\",primes_below(50)\nend\n```\n\noutput: `2,3,5,7,11,13,17,19,23,29,31,37,41,43,47`\n\n----\n\n**Print a table of powers for integers from 1 to 10.**\n\n**Haskell**\n\n```Haskell\nimport Text.Printf\n\nn = 10\npowers = [1/2, 1/3, 2/3]\n\nmain :: IO ()\nmain = do\n    printLabels powers\n    mapM_ printPowers ([1..n] :: [Integer])\n  where\n    printLabels powers = do\n      putStrLn $ printf \"%12s\" \"i\" ++ concat (map (printf \"%12s\" . ((\"pow(\" ++) . (++ \")\") . printf \"%.3f\")) powers)\n    printPowers i = do\n      putStrLn $ printf \"%12d\" i ++ concat (map (printf \"%12.4f\" . ((fromIntegral i :: Double) **)) powers)\n```\n\noutput:\n```\n           i  pow(0.500)  pow(0.333)  pow(0.667)\n           1      1.0000      1.0000      1.0000\n           2      1.4142      1.2599      1.5874\n           3      1.7321      1.4422      2.0801\n           4      2.0000      1.5874      2.5198\n           5      2.2361      1.7100      2.9240\n           6      2.4495      1.8171      3.3019\n           7      2.6458      1.9129      3.6593\n           8      2.8284      2.0000      4.0000\n           9      3.0000      2.0801      4.3267\n          10      3.1623      2.1544      4.6416\n```\n\n**Fortran**\n\n```Fortran\nprogram main\nimplicit none\ninteger, parameter :: n = 10\ndouble precision, parameter :: powers(*) = [1/2.0d0, 1/3.0d0, 2/3.0d0]\ninteger :: i\nprint \"(a12,*(:,3x,'pow(',f5.3,')'))\", \"i\", powers\ndo i=1,10\n   print \"(i12,*(f12.4))\", i, i**powers\nend do\nend\n```\n\noutput:\n```\n           i   pow(0.500)   pow(0.333)   pow(0.667)\n           1      1.0000      1.0000      1.0000\n           2      1.4142      1.2599      1.5874\n           3      1.7321      1.4422      2.0801\n           4      2.0000      1.5874      2.5198\n           5      2.2361      1.7100      2.9240\n           6      2.4495      1.8171      3.3019\n           7      2.6458      1.9129      3.6593\n           8      2.8284      2.0000      4.0000\n           9      3.0000      2.0801      4.3267\n          10      3.1623      2.1544      4.6416\n```\n---\n**Create functions to compute the mean and standard deviation of an array and compute the mean, standard deviation, minimum, and maximum of [10.0, 20.0, 30.0, 40.0]**\n\n**Haskell**\n\n```Haskell\nstats :: [Double] -\u003e (Double, Double, Double, Double)\nstats xs = (mean xs, stddev xs, minimum xs, maximum xs)\n\nmean :: [Double] -\u003e Double\nmean xs = sum xs / fromIntegral (length xs)\n\nstddev :: [Double] -\u003e Double\nstddev xs = sqrt $ sum [(x - m) ** 2 | x \u003c- xs] / fromIntegral (length xs - 1)\n  where m = mean xs\n\nmain :: IO ()\nmain = print $ stats [10.0, 20.0, 30.0, 40.0]\n```\n\noutput: `(25.0,12.909944487358056,10.0,40.0)`\n\n**Fortran**\n\n```Fortran\nmodule stats_mod\n  implicit none\n  integer, parameter :: dp = kind(1.0d0)\ncontains\n  function stats(x)\n    real(kind=dp), intent(in) :: x(:)\n    real(kind=dp) :: stats(4)\n    stats = [mean(x), stddev(x), minval(x), maxval(x)]\n  end function stats\n  \n  real(kind=dp) function mean(x)\n    real(kind=dp), intent(in) :: x(:)\n    mean = sum(x)/size(x)\n  end function mean\n\n  real(kind=dp) function stddev(x)\n    real(kind=dp), intent(in) :: x(:)\n    stddev = sqrt(sum((x - mean(x))**2) / (size(x) - 1))\n  end function stddev\nend module stats_mod\n\nprogram main\n  use stats_mod\n  implicit none\n  print*,stats([10.0_dp, 20.0_dp, 30.0_dp, 40.0_dp])\nend\n```\n\noutput: `25.000000000000000        12.909944487358056        10.000000000000000        40.000000000000000     `\n\n---\n\n**Define functions to compute the mean and standard deviation in one source file and call those functions from a main program.**\n\n**Haskell**\n\nfile `stats.hs`\n```Haskell\nmodule Stats (mean, stddev) where\n\nmean :: [Double] -\u003e Double\nmean xs = sum xs / fromIntegral (length xs)\n\nstddev :: [Double] -\u003e Double\nstddev xs = sqrt $ sum [(x - m) ** 2 | x \u003c- xs] / fromIntegral (length xs - 1)\n  where m = mean xs\n```\n\nfile `xstats.hs`\n```Haskell\nimport Stats (mean, stddev)\n\nmain :: IO ()\nmain = do\n    let xs = [10.0, 20.0, 30.0, 40.0]\n    putStrLn $ \"Mean: \" ++ show (mean xs)\n    putStrLn $ \"Standard Deviation: \" ++ show (stddev xs)\n```\n\nCompile with `ghc xstats.hs`.\n\noutput:\n```\nMean: 25.0\nStandard Deviation: 12.909944487358056\n```\n\n**Fortran**\n\nModule `stats_mod` was defined above and is stored in `stats.f90`. The main program is\n\nfile `main.f90`\n```Fortran\n  use stats_mod\n  implicit none\n  real(kind=dp), parameter :: x(*) = [10.0_dp, 20.0_dp, 30.0_dp, 40.0_dp]\n  print*,\"Mean:\", mean(x)\n  print*,\"Standard Deviation:\", stddev(x)\nend program\n```\n\nCompile with `gfortran stats.f90 main.f90`\u003cbr\u003e\noutput:\n```\n Mean:   25.000000000000000     \n Standard Deviation:   12.909944487358056\n```\n\n---\n\n**Matrix operations**\n\n**Haskell**\n```Haskell\n{-# LANGUAGE FlexibleContexts #-}\n\nimport Prelude hiding ((\u003c\u003e))\nimport Numeric.LinearAlgebra\n\nmain :: IO ()\nmain = do\n    -- Create a 3x3 matrix\n    let a = (3\u003e\u003c3) [1..9] :: Matrix R\n    putStrLn \"Matrix a:\"\n    print a\n\n    putStrLn \"\\n Matrix a squared:\"\n    print $ a \u003c\u003e a\n\n    putStrLn \"\\n Transpose:\"\n    print $ tr a\n\n    putStrLn \"\\n Maximum:\"\n    print $ maxElement a\n\n    putStrLn \"\\n Sum:\"\n    print $ sumElements a\n\n    putStrLn \"\\n Sum of each column:\"\n    print $ fromList [sumElements v | v \u003c- toColumns a]\n\n -- rows and columns are numbered from 0\n    putStrLn \"\\n element in 2nd row and 3rd column:\"\n    print $ a `atIndex` (1,2)\n\n    putStrLn \"\\n 2nd row:\"\n    print (a ? [1])\n\n    putStrLn \"\\n 2nd column:\"\n    print (tr a ? [1])\n\n    putStrLn \"\\n twice a:\"\n    print $ cmap (*2) a\n```\noutput:\n```\nMatrix a:\n(3\u003e\u003c3)\n [ 1.0, 2.0, 3.0\n , 4.0, 5.0, 6.0\n , 7.0, 8.0, 9.0 ]\n\n Matrix a squared:\n(3\u003e\u003c3)\n [  30.0,  36.0,  42.0\n ,  66.0,  81.0,  96.0\n , 102.0, 126.0, 150.0 ]\n\n Transpose of matrix a:\n(3\u003e\u003c3)\n [ 1.0, 4.0, 7.0\n , 2.0, 5.0, 8.0\n , 3.0, 6.0, 9.0 ]\n\n Maximum of matrix a:\n9.0\n\n Sum of elements of matrix a:\n45.0\n\n Sum of each column in matrix a:\n[12.0,15.0,18.0]\n\n element in 2nd row and 3rd column:\n6.0\n\n 2nd row:\n(1\u003e\u003c3)\n [ 4.0, 5.0, 6.0 ]\n\n 2nd column:\n(1\u003e\u003c3)\n [ 2.0, 5.0, 8.0 ]\n\n twice a:\n(3\u003e\u003c3)\n [  2.0,  4.0,  6.0\n ,  8.0, 10.0, 12.0\n , 14.0, 16.0, 18.0 ]\n```\n\n**Fortran**\n```Fortran\nmodule m\n  implicit none\ncontains\n  subroutine print_mat(x)\n    real, intent(in) :: x(:,:)\n    integer          :: i\n    do i=1,size(x,1)\n       print \"(*(f8.1))\", x(i,:)\n    end do\n  end subroutine print_mat\nend module m\n\nprogram main\n  use m\n  implicit none\n  integer, parameter :: n = 3\n  real :: a(n,n)\n  integer :: i\n  character (len=*), parameter :: fmt_c = \"(/,a)\", fmt_r = \"(*(f8.1))\"\n  a = transpose(reshape([(i, i=1,n**2)], [n,n]))\n  print fmt_c, \"Matrix a:\"\n  call print_mat(a)\n\n  print fmt_c, \"Matrix a squared:\"\n  call print_mat(matmul(a,a))\n\n  print fmt_c, \"Transpose:\"\n  call print_mat(transpose(a))\n\n  print fmt_c, \"Maximum:\"\n  print fmt_r, maxval(a)\n\n  print fmt_c, \"Sum:\"\n  print fmt_r, sum(a)\n\n  print fmt_c, \"Sum of each column:\"\n  print fmt_r, sum(a, dim=1)\n\n  print fmt_c, \"element in 2nd row and 3rd column\"\n  print fmt_r, a(2,3)\n\n  print fmt_c, \"2nd row\"\n  print fmt_r, a(2,:)\n\n  print fmt_c, \"2nd column\"\n  print fmt_r, a(:,2)\n\n  print fmt_c, \"twice a\"\n  call print_mat(2*a)\nend\n```\n\noutput:\n```\nMatrix a:\n     1.0     2.0     3.0\n     4.0     5.0     6.0\n     7.0     8.0     9.0\n\nMatrix a squared:\n    30.0    36.0    42.0\n    66.0    81.0    96.0\n   102.0   126.0   150.0\n\nTranspose:\n     1.0     4.0     7.0\n     2.0     5.0     8.0\n     3.0     6.0     9.0\n\nMaximum:\n     9.0\n\nSum:\n    45.0\n\nSum of each column:\n    12.0    15.0    18.0\n\nelement in 2nd row and 3rd column\n     6.0\n\n2nd row\n     4.0     5.0     6.0\n\n2nd column\n     2.0     5.0     8.0\n\ntwice a\n     2.0     4.0     6.0\n     8.0    10.0    12.0\n    14.0    16.0    18.0\n```\n\n---\n**Define a data type date(year, month), and write functions to print it and create a sequence of dates**\n\n**Haskell**\n\nfile `dateutils.hs`\n\n```Haskell\nmodule DateUtils (Date(..), strDate, seqDate) where\n\nimport Text.Printf (printf)\n\ndata Date = Date{year :: Int, month :: Int} deriving (Show, Eq)\n\n-- Convert a Date to a string in the format \"yyyy-mm\"\nstrDate :: Date -\u003e String\nstrDate (Date y m) = printf \"%04d-%02d\" y m\n\n-- Generate a sequence of dates, starting from a given date and for a given number of months\nseqDate :: Date -\u003e Int -\u003e [Date]\nseqDate startDate numDates = take numDates $ iterate nextMonth startDate\n  where\n    nextMonth (Date y m) \n        | m \u003c 12 = Date y (m + 1)\n        | otherwise = Date (y + 1) 1\n```\n\nmain program\n```Haskell\nimport DateUtils (Date(..), strDate, seqDate)\n\nmain :: IO ()\nmain = do\n    mapM_ (putStrLn . strDate) $ seqDate Date{year = 2023, month = 11} 4\n```\n\noutput:\n```\n2023-11\n2023-12\n2024-01\n2024-02\n```\n\n**Fortran**\n\n```Fortran\nmodule DateUtils\n  implicit none\n  type :: Date\n     integer :: year, month\n  end type Date\ncontains\n  elemental character (len=7) function strDate(xDate)\n    ! Convert a Date to a string in the format \"yyyy-mm\"\n    type(Date), intent(in) :: xDate\n    write (strDate,\"(i4.4,'-',i2.2)\") xDate\n  end function strDate\n\n  function seqDate(xDate, numDates) result(Dates)\n    ! Generate a sequence of dates, starting from a given date and for a given number of months\n    type(Date), intent(in) :: xDate\n    integer, intent(in) :: numDates\n    type(Date) :: Dates(numDates)\n    integer :: i\n    if (numDates \u003c 1) return\n    Dates(1) = xDate\n    do i=2,numDates\n       if (Dates(i-1)%month == 12) then\n          Dates(i) = Date(Dates(i-1)%year + 1, 1)\n       else\n          Dates(i) = Date(Dates(i-1)%year, Dates(i-1)%month + 1)\n       end if\n    end do\n  end function seqDate\nend module DateUtils\n\nprogram main\n  use DateUtils\n  implicit none\n  print \"(a)\", strDate(seqDate(Date(2023, 11), 4))\nend program main\n```\n\noutput:\n```\n2023-11\n2023-12\n2024-01\n2024-02\n```\n\n---\n**Compute the complex roots of a quadratic equation**\n\n**Haskell**\n```Haskell\nimport Data.Complex\n\n-- The function roots takes three Complex numbers a, b, and c\n-- (representing the coefficients of the quadratic equation ax^2 + bx + c = 0),\n-- and returns a pair of Complex numbers (representing the two roots of the equation).\nroots :: (RealFloat a) =\u003e Complex a -\u003e Complex a -\u003e Complex a -\u003e (Complex a, Complex a)\nroots a b c = ((-b + sqrt (b*b - 4*a*c)) / (2*a), (-b - sqrt (b*b - 4*a*c)) / (2*a))\n\nmain :: IO ()\nmain = do\n-- Here \":+\" is used to create a complex number. The number before \":+\" is the real part,\n-- and the number after \":+\" is the imaginary part.\n    let a = (1.0 :+ 0.0)\n    let b = ((-2.0) :+ 3.0)\n    let c = (0.0 :+ (-6.0))\n    putStrLn $ \"Coefficients of the equation:\"\n    putStrLn $ \"a = \" ++ show a\n    putStrLn $ \"b = \" ++ show b\n    putStrLn $ \"c = \" ++ show c\n    let (root1, root2) = roots a b c\n    putStrLn \"Roots:\"\n    print root1\n    print root2\n```\n\noutput:\n```\nCoefficients of the equation:\na = 1.0 :+ 0.0\nb = (-2.0) :+ 3.0\nc = 0.0 :+ (-6.0)\nRoots:\n2.0 :+ 0.0\n0.0 :+ (-3.0)\n```\n\n**Fortran** (default reals have been used in this code for simplicity)\n```Fortran\nmodule quadratic_mod\n  implicit none\n  contains\n\n! The subroutine roots takes three Complex numbers a, b, and c\n! (representing the coefficients of the quadratic equation ax^2 + bx + c = 0),\n! and returns a pair of Complex numbers (representing the two roots of the equation).\n    subroutine roots(a, b, c, root1, root2)\n    complex, intent(in) :: a, b, c\n    complex, intent(out) :: root1, root2\n    root1 = ((-b + sqrt(b*b - 4.0*a*c)) / (2.0*a))\n    root2 = ((-b - sqrt(b*b - 4.0*a*c)) / (2.0*a))\n  end subroutine roots\nend module quadratic_mod\n\nprogram main\n  use quadratic_mod\n  implicit none\n  complex :: a, b, c, root1, root2\n\n  a = (1.0, 0.0)\n  b = (-2.0, 3.0)\n  c = (0.0, -6.0)\n\n  print*, \"Coefficients of the equation are\"\n  print*, \"a = \", a\n  print*, \"b = \", b\n  print*, \"c = \", c\n\n  call roots(a, b, c, root1, root2)\n\n  print*, \"Roots are:\"\n  print*, root1\n  print*, root2\nend program main\n```\n\noutput:\n```\n Coefficients of the equation are\n a =              (1.00000000,0.00000000)\n b =             (-2.00000000,3.00000000)\n c =             (0.00000000,-6.00000000)\n Roots are:\n             (2.00000000,0.00000000)\n            (0.00000000,-3.00000000)\n```\n\n---\n**Read a matrix from a file, where the first line contains the dimensions of the matrix and following lines contain rows of the matrix.**\n\nFile `data.txt` contains\n```\n2 3\n10.0 20.0 30.0\n40.0 50.0 60.0\n```\n\n**Haskell**\n```Haskell\nimport System.IO\nimport Data.List.Split\nimport Text.Read\n\n-- Function to convert a string to a list of Doubles\nstrToDoubleList :: String -\u003e [Double]\nstrToDoubleList s = map read (words s)\n\n-- Main function\nmain :: IO ()\nmain = do\n  -- Open the file\n  handle \u003c- openFile \"data.txt\" ReadMode\n  -- Read the first line\n  dims \u003c- hGetLine handle\n  let [rows, cols] = map read $ words dims\n  -- Read the rest of the file\n  contents \u003c- hGetContents handle\n  -- Split the contents into lines, then convert each line to a list of Doubles\n  let matrix = map strToDoubleList (take rows (lines contents))\n  -- Print the matrix\n  mapM_ print matrix\n  -- Close the file\n  hClose handle\n```\n\noutput:\n```\n[10.0,20.0,30.0]\n[40.0,50.0,60.0]\n```\n\n**Fortran**\n\n```Fortran\nprogram read_matrix\n    implicit none\n    integer :: i, rows, cols, iu\n    integer, parameter :: dp = kind(1.0d0)\n    real(kind=dp), allocatable :: matrix(:,:)\n    open(newunit=iu, file='data.txt', action=\"read\")\n\n    ! Read the number of rows and columns\n    read(iu, *) rows, cols\n\n    ! Allocate the matrix\n    allocate(matrix(rows, cols))\n\n    ! Read the matrix\n    do i = 1, rows\n        read(iu, *) matrix(i, 1:cols)\n    end do\n\n    ! Print the matrix\n    do i = 1, rows\n        print *, matrix(i, 1:cols)\n    end do\n\n    ! Close the file\n    close(iu)\nend program read_matrix\n```\n\noutput:\n```\n   10.000000000000000        20.000000000000000        30.000000000000000     \n   40.000000000000000        50.000000000000000        60.000000000000000\n```\n\n---\n**Read an unknown number of integers from a file, one per line**\n\nThe file `integers.txt` has contents\n```\n10\n20\n30\n```\n\n**Haskell**\n```Haskell\nmain = do\n    content \u003c- readFile \"integers.txt\"           -- Read the content of the file\n    let linesOfFiles = lines content             -- Split the content by newlines\n    let numbers = map read linesOfFiles :: [Int] -- Convert each line to an integer\n    print numbers                                -- Print the list of numbers\n```\noutput:\n```\n[10,20,30]\n```\n**Fortran**\n```Fortran\nprogram main\n  implicit none\n  integer, parameter :: max_read = 10**6\n  integer, allocatable :: numbers(:)\n  integer :: i,iu,ierr\n  allocate (numbers(max_read))\n  open (newunit=iu, file=\"integers.txt\", action=\"read\") ! open the file\n  do i=1,max_read\n     read (iu,*,iostat=ierr) numbers(i) ! try to read an integer\n     if (ierr /= 0) then \n        numbers = numbers(:i-1) ! resize numbers and exit loop if integer could not be read\n        exit\n     end if\n  end do\n  print*,numbers\nend program main\n```\noutput:\n```\n          10          20          30\n```\n\n---\n\n**Write a generic function that returns the positions of changed elements, including the first position, in a 1-D array.**\n\n**Haskell**\n\n```Haskell\n-- The changePositions function takes a list of any type that supports equality testing as input.\n-- If the input list is empty, it returns an empty list.\n-- If the input list is not empty, it returns a list containing 0 followed by the positions of changes in the input list.\nchangePositions :: Eq a =\u003e [a] -\u003e [Int]\nchangePositions [] = [] -- Base case: if the input list is empty, return an empty list.\nchangePositions xs = 0 : [i | (i, (x, y)) \u003c- zip [1..] (zip xs (tail xs)), x /= y]\n-- Recursive case: if the input list is not empty...\n-- 1. Zip the input list with its tail, creating a list of pairs, where each pair consists of an element of xs and its successor.\n-- 2. Zip this list of pairs with the list [1..], effectively assigning an index to each pair.\n-- 3. Use a list comprehension to select the indices where a change occurred (i.e., where the two elements in a pair are not equal).\n-- 4. Prepend 0 to the resulting list.\n\nmain :: IO ()\nmain = do -- test with lists of integer and strings\n    print $ changePositions [3, 3, 6, 2, 2, 2, 1] -- Expected output: [0, 2, 3, 6]\n    print $ changePositions [\"a\", \"a\", \"b\", \"p\", \"p\", \"p\", \"o\"] -- Expected output: [0, 2, 3, 6]\n```\n\n```\n[0,2,3,6]\n[0,2,3,6]\n```\n\n**Fortran** (works only for integers and character variables)\n\n```Fortran\nmodule list_mod\n  implicit none\n  interface change_positions\n     module procedure :: change_positions_int, change_positions_char\n  end interface change_positions\ncontains\n  function change_positions_int(vec) result(pos)\n    integer, intent(in)  :: vec(:)\n    integer, allocatable :: pos(:)\n    integer :: i,j,n\n    n = size(vec)\n    allocate (pos(n))\n    if (n \u003c 1) return\n    pos = 0\n    pos(1) = 1\n    j = 1\n    do i=2,n\n       if (vec(i) /= vec(i-1)) then\n          j = j+1\n          pos(j) = i\n       end if\n    end do\n    pos = pack(pos, pos \u003e 0)\n  end function change_positions_int\n\n  function change_positions_char(vec) result(pos)\n    character (len=*), intent(in)  :: vec(:)\n    integer, allocatable :: pos(:)\n    integer :: i,j,n\n    n = size(vec)\n    allocate (pos(n))\n    if (n \u003c 1) return\n    pos = 0\n    pos(1) = 1\n    j = 1\n    do i=2,n\n       if (vec(i) /= vec(i-1)) then\n          j = j+1\n          pos(j) = i\n       end if\n    end do\n    pos = pack(pos, pos \u003e 0)\n  end function change_positions_char\nend module list_mod\n!\nprogram main\n  use list_mod\n  implicit none\n  print*,change_positions([3, 3, 6, 2, 2, 2, 1])\n    print*,change_positions([\"a\", \"a\", \"b\", \"p\", \"p\", \"p\", \"o\"])\nend program main\n```\n\noutput:\n```\n           1           3           4           7\n           1           3           4           7\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeliavsky%2Fhaskell_and_fortran","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeliavsky%2Fhaskell_and_fortran","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeliavsky%2Fhaskell_and_fortran/lists"}