这个“where”子句的正确 Haskell 语法是什么?

wid*_*pil 1 haskell where-clause

该语法的适当更正是什么?这是一个空白问题吗?我复制了LYAH示例中使用的空格,还尝试了从SO 答案中收集的其他变体。

\n

我确信有更好的方法来编写这个,但我还不太擅长点免费代码。我是新手,试图掌握非常基本的语法,但通过大量的代码战争练习,这些语法仍然让我犯难。

\n
import Data.List (findIndices)\n\nbasicOp :: Char -> Int -> Int -> Int\nbasicOp x y z = (operations  !! (op x)) y z\n    where op x = head $ findIndices (== x) "+-*/" :: Char -> Int\n    operations = [(+), (-), (*), (div)]  :: [(Int -> Int -> Int)]\n
Run Code Online (Sandbox Code Playgroud)\n

当我像这样编写一个函数并引用其他两个函数时,它会起作用。

\n
import Data.List (findIndices)\n\noperations :: [(Int -> Int -> Int)]\noperations = [(+), (-), (*), (div)]\n\nop :: Char -> Int\nop x = head $ findIndices (== x) "+-*/" \n\nbasicOp :: Char -> Int -> Int -> Int\nbasicOp x y z = (operations  !! (op x)) y z\n
Run Code Online (Sandbox Code Playgroud)\n

带有 where 子句的代码返回以下错误:

\n
codewars.hs:103:34: error:\n    \xe2\x80\xa2 Couldn\'t match expected type \xe2\x80\x98Int\xe2\x80\x99 with actual type \xe2\x80\x98Char -> Int\xe2\x80\x99\n    \xe2\x80\xa2 Probable cause: \xe2\x80\x98op\xe2\x80\x99 is applied to too few arguments\n      In the second argument of \xe2\x80\x98(!!)\xe2\x80\x99, namely \xe2\x80\x98(op x)\xe2\x80\x99\n      In the expression: (operations !! (op x)) y z\n      In an equation for \xe2\x80\x98basicOp\xe2\x80\x99:\n          basicOp x y z\n            = (operations !! (op x)) y z\n            where\n                op x = head $ findIndices (== x) "+-*/" :: Char -> Int\n                operations = [(+), ....] :: [(Int -> Int -> Int)]\n    |\n103 | basicOp x y z = (operations  !! (op x)) y z\n    |                                  ^^^^\n\ncodewars.hs:104:18: error:\n    \xe2\x80\xa2 Couldn\'t match expected type \xe2\x80\x98Char -> Int\xe2\x80\x99 with actual type \xe2\x80\x98Int\xe2\x80\x99\n    \xe2\x80\xa2 Possible cause: \xe2\x80\x98($)\xe2\x80\x99 is applied to too many arguments\n      In the expression: head $ findIndices (== x) "+-*/" :: Char -> Int\n      In an equation for \xe2\x80\x98op\xe2\x80\x99:\n          op x = head $ findIndices (== x) "+-*/" :: Char -> Int\n      In an equation for \xe2\x80\x98basicOp\xe2\x80\x99:\n          basicOp x y z\n            = (operations !! (op x)) y z\n            where\n                op x = head $ findIndices (== x) "+-*/" :: Char -> Int\n                operations = [(+), ....] :: [(Int -> Int -> Int)]\n    |\n104 |     where op x = head $ findIndices (== x) "+-*/" :: Char -> Int\n    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n
Run Code Online (Sandbox Code Playgroud)\n

我最初的尝试可能更容易阅读,但这只是尝试使用更多我还不熟悉的 Haskell 结构的练习。

\n
basicOp :: Char -> Int -> Int -> Int\nbasicOp oper x y\n    | oper == \'+\'  = (+)   x y \n    | oper == \'-\'  = (-)   x y\n    | oper == \'*\'  = (*)   x y\n    | oper == \'/\'  = (div) x y\n
Run Code Online (Sandbox Code Playgroud)\n

根据@DanielWagner 的评论,这已改进为:

\n
basicOp c = case c of\n    \'+\' -> (+)\n    \'-\' -> (-)\n    \'*\' -> (*)\n    \'/\' -> div\n
Run Code Online (Sandbox Code Playgroud)\n

Wil*_*sem 5

表达式主体的类型op x是 an Int,而不是 a Char -> Int。您还应该定位operations在与 相同的列op,因此:

\n
basicOp :: Char -> Int -> Int -> Int\nbasicOp x y z = (operations  !! (op x)) y z\n    where op x = head $ findIndices (== x) "+-*/" :: Int\n          operations = [(+), (-), (*), (div)]  :: [(Int -> Int -> Int)]\n
Run Code Online (Sandbox Code Playgroud)\n

但类型不是必需的,您可以将其简化为:

\n
basicOp :: Char -> Int -> Int -> Int\nbasicOp x = (operations  !! op x)\n    where op x = head $ findIndices (== x) "+-*/"\n          operations = [(+), (-), (*), (div)]\n
Run Code Online (Sandbox Code Playgroud)\n

并与lookup :: Eq a => a -> [(a, b)] -> Maybe b

\n
basicOp :: Char -> Int -> Int -> Int\nbasicOp x | Just y <- lookup x operations = y\n          | otherwise = …\n    where operations = [(\'+\', (+)), (\'-\', (-)), (\'*\', (*)), (\'/\', div)]
Run Code Online (Sandbox Code Playgroud)\n

其中\xe2\x80\xa6是一个表达式,如果未找到该键,则对该表达式进行求值

\n