Haskell也许类型 - >类型

时间:2016-01-05 22:21:11

标签: haskell maybe

我遇到了这个问题:

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>>

2 个答案:

答案 0 :(得分:5)

是的,您可以使用fromMaybe功能:

fromMaybe :: a -> Maybe a -> a

它的工作原理如下,第一个参数是默认值,如果第二个参数是Nothing,则使用的是下一个Maybe a,如果该值是Just xx被退回。因此fromMaybe的实现可能是:

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

所以你可以使用:

import Data.Maybe(fromMaybe)

--...

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

如果没有if-then-else,那么 un-Haskell

为什么会循环播放?如果您的index格式为Just x,则会进入以下分支:

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

现在表达式:

   let index = index

表示您将index 分配给自己(而非外部index)。这在功能性编程语言中并不是真正的问题,但如果你想要使用这样的功能会出现问题。

答案 1 :(得分:5)

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

首先使用你的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不允许你覆盖现有的变量,但它会让你隐藏它们。但通常最好在末尾用“素数”符号(')标记变量的“修改”版本。这样,如果需要,您可以随时访问原始文件。

其次,您可以使用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'

你也可以使用警卫。但由于我不知道你的代码片段来自何处,我不知道使用警卫是否合理。

您可以阅读有关警卫,案例表达和模式匹配的更多信息here

相关问题