Вы совсем близко. Фактически мы можем легко получить тип something
, используя " hole " (_
) в ghci
:
Prelude Data.Either> :{
Prelude Data.Either| inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
Prelude Data.Either| inExpr = either Num _
Prelude Data.Either| :}
<interactive>:36:21: error:
• Found hole: _ :: (Op, (Expr, Expr)) -> Expr
• In the second argument of ‘either’, namely ‘_’
In the expression: either Num _
In an equation for ‘inExpr’: inExpr = either Num _
• Relevant bindings include
inExpr :: Either Int (Op, (Expr, Expr)) -> Expr
(bound at <interactive>:36:1)
Итак, мы знаем, что эта функция _
должна иметь тип (Op, (Expr, Expr)) -> Expr
.
Мы можем, например, использовать здесь лямбда-выражение:
inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
inExpr = either Num <b>(\(o, (l, r)) -> Bop l o r)</b>
Таким образом, мы «распаковываем» кортеж и поднабор с шаблоном (o, (l, r))
, а затем создаем Expr
, используя конструктор данных Bop
с l
, o
и r
в качестве аргументов .
При этом простое сопоставление с образцом, например, в заголовке функции, также поможет, и, возможно, легче понять:
inExpr :: Either Int (Op,(Expr,Expr)) -> Expr
inExpr (Left a) = Num a
inExpr (Right (o, (l, r))) = Bop l o r