Haskell 也许输入 -> 输入

Haskell Maybe type -> type

我 运行 遇到这个问题 :

Couldn't match expected type ‘Int’ with actual type ‘Maybe Int’

我能否以某种方式将“Maybe Int”转换为“Int”?

if index == Nothing 
   then 
     do 
       let index = 0
       putStrLn(fancyPrint2 $ kaasasOlevList !! index)
   else 
     do 
       let index = index
       putStrLn(fancyPrint2 $ kaasasOlevList !! index)

我这样试过,但这给了我:

Exception: <<loop>>

是的,你可以使用fromMaybe函数:

fromMaybe :: a -> Maybe a -> a

它的工作原理如下,第一个参数是 默认值 ,第二个参数是 Nothing,接下来是 Maybe a ,如果该值为 Just x,则返回 x。所以 fromMaybe 的实现可以是:

fromMaybe _ (Just x) = x
fromMaybe d Nothing = d

所以你可以使用:

import Data.Maybe(fromMaybe)

--...

putStrLn(fancyPrint2 $ kaasasOlevList !! (fromMaybe 0 index))

没有所有 if-then-else 而是 un-Haskell.


为什么会循环?好吧,如果你的 indexJust x 的形式,它会进入以下分支:

do 
   let index = index
   putStrLn(fancyPrint2 $ kaasasOlevList !! index)

现在表达式:

   let index = index

表示你将index赋值给自身(不是外层的index)。这在函数式编程语言中并不是真正的问题,尽管如果您希望使用这样的函数

就会出现问题

您有几种不同的选择来解决这个问题

首先是使用您的 if 语句,但稍作修改(不过请避免这样做)

if index == Nothing 
   then 
     do 
       let index' = 0
       putStrLn $ fancyPrint2 $ kaasasOlevList !! index'
   else 
     do 
       let (Just index') = index
       putStrLn $ fancyPrint2 $ kaasasOlevList !! index'

我在这里写 index',因为 Haskell 不允许您覆盖现有变量,但是它允许您隐藏它们。但一般来说,更好的做法是在变量的 "modified" 版本末尾使用 "prime" 符号 (') 进行标记。这样您就可以在需要时随时访问原件。

其次,您可以使用 case 表达式将您的代码变成

case index of
  Just i  -> putStrLn $ fancyPrint2 $ kaasasOlevList !! i
  Nothing -> putStrLn $ fancyPrint2 $ kaasasOlevList !! 0

或者如果您使用 where 子句稍微清理一下:

case index of
  Just i  -> putIndex i
  Nothing -> putIndex 0
where putIndex x = putStrLn $ fancyPrint2 $ kaasasOlevList !! x

最后还有 fromMaybe 可以让你这样做:

import Data.Maybe (fromMaybe)

-- ...

do
  let index' = fromMaybe 0 index
  putStrLn $ fancyPrint2 $ kaasasOlevList !! index'

你也可以使用守卫。但是看到我不知道你的 code-snippet 来自哪里,我不知道使用守卫是否合理。

您可以阅读更多关于守卫、case 表达式和模式匹配的内容here